package br;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.awt.List;
import java.io.InputStream;
import java.io.OutputStream;

public class interfaceSerial implements SerialPortEventListener
{	
	
	//configuraes de comunicacao com a placa
	private SerialPort serialPort = null;
	private int baudRate = 19200;  //velocidade de comunicacao
	private String porta = "COM1";  //porta de comunicacao
	private InputStream in = null;  //entrada de dados
	private OutputStream out = null;  //saida de dados
	private boolean desconectado = true; 
	/////////////////////////////////////
	
	
	//variaveis de armazenamento dos dados recebidos
	private List listDados = null;
	
	
	//variavel para saber se grafico  em tempo real
	private boolean graficoTempoReal = false;
	final int atualizar = 30; // Quantos dados lidos para atualizar
	private int contadorAtualizar = 0;
	private float pico = 0f;
	
	Grafico g = null;
	
	
	public interfaceSerial(List listDados){
		this.listDados = listDados;
	}
	
	
	//faz porta de comuicacao
    public void conecta ()
    {
    	try{
	        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(porta);
	        
	        if ( portIdentifier.isCurrentlyOwned() )
	        {
	            System.out.println("Erro: Porta esta em uso!");
	        }
	        
	        else
	        {
	            serialPort = (SerialPort) portIdentifier.open("Serial" , 20);
	            
	            
	        	in = serialPort.getInputStream();
	            out = serialPort.getOutputStream();
	            
	            serialPort.addEventListener(this);
	            serialPort.notifyOnDataAvailable(true);
	            
	            serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
	            
	            desconectado = false;
	            
	            out.write('s'); //sincroniza e avisa placa para converter e enviar dados
	 
	        }   
    	}catch (Exception e){
    		System.out.print("Erro Conecta!");
    		e.printStackTrace();
    	}
    }
    
    //fecha porta de comunicacao
    public void desconecta(){ 
    	try { 
    		out.write('p'); //envia 'p' para avisar o microcontrolador para parar enviar e converter
    		
    		if (in != null) in.close(); 
			if (out !=null) out.close(); 
			if (serialPort != null) serialPort.close(); 
			
			in = null; 
			out = null; 
			serialPort = null; 
			desconectado = true;
	    }catch(Exception e){ 
	    	System.out.println("Erro ao desconectar"); 
	    }
    }

	//envia dados para a placa
    public void enviaDado(int dado){
    	try{
    		out.write(dado);
    	}catch (Exception e){
    		e.printStackTrace();
    	}
    }

	//recebe dados da placa
	public void serialEvent(SerialPortEvent evento){
		if (evento.getEventType() == SerialPortEvent.DATA_AVAILABLE){
			byte[] buffer = new byte[1024];
			int len = 0, countLen = 0;
			int ADRESH = 0, ADRESL = 0;
			float valor = 0f;
			int qtdDadosRecebidosPorVez = 3; //quantidade de dados enviados pela placa por vez
			
			try {
				len = in.read(buffer);
				while (countLen < len){
					if (desconectado) return;
					//desloca 8 bits para esquerda, pois  o non e decimo bit da conversao
					if ((buffer[countLen]) != 's'){ //verifica se esta sincronizado
						countLen++;
						continue;
					}
					if (countLen+3 > len) break; //garante sincronia
					ADRESH = (buffer[countLen+1]) << 8; 
					ADRESL = (buffer[countLen+2]);
					if (ADRESH < 0) ADRESH = ADRESH + 256;  
					if (ADRESL < 0) ADRESL = ADRESL + 256;
					valor = (float) (ADRESH + ADRESL);
					//valor = valor * 5; //aumentar para mais facil vizualizacao
					//listDados.add(String.valueOf(valor));
					if (valor > pico) pico = valor; //valores ficam menos oscilosos
					if (contadorAtualizar > atualizar){
						listDados.add(String.valueOf(pico));
						if (isGraficoTempoReal()){
								g.atualizaGrafico(pico);
						}
						pico = 0;
						contadorAtualizar = 0;
					}
					contadorAtualizar++;
					countLen += qtdDadosRecebidosPorVez;
				}
			} catch (Exception e) {
				e.printStackTrace();
				
			}
		}
	}


	public void setGraficoTempoReal(boolean graficoTempoReal) {
		this.graficoTempoReal = graficoTempoReal;
	}


	public boolean isGraficoTempoReal() {
		return graficoTempoReal;
	}
	
	public void setG(Grafico g){
		this.g = g;
	}
	
	public Grafico getG(){
		return this.g;
	}
	
	public void apagaG(){
		g.dispose();
		g = null;
	}
}
