package de.nanoleaf.tools.panelconfig;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.eclnt.editor.annotations.CCGenClass;
import org.eclnt.jsfserver.base.faces.event.ActionEvent;
import org.eclnt.jsfserver.defaultscreens.OKPopup;
import org.eclnt.jsfserver.defaultscreens.Statusbar;
import org.eclnt.jsfserver.elements.componentnodes.PANENode;
import org.eclnt.jsfserver.elements.events.BaseActionEventDrop;
import org.eclnt.jsfserver.elements.events.BaseActionEventInvoke;
import org.eclnt.jsfserver.elements.impl.ROWDYNAMICCONTENTBinding;
import org.eclnt.jsfserver.elements.impl.ROWDYNAMICCONTENTBinding.ComponentNode;
import org.eclnt.jsfserver.elements.util.ValidValuesBinding;

import de.nanoleaf.server.ColorEnum;
import de.nanoleaf.server.NanoleafDeviceServer;
import de.tvo.database.tables.NLCONNECT.Nlconnect;
import de.tvo.database.tables.NLCONNECT.NlconnectWorker;
import de.tvo.nanoleaf.enums.NanoTypeEnum;
import de.tvo.nanoleaf.oclasses.MatrixInfo;
import de.tvo.tools.StringUtil;
import de.tvo.workplace.DefaultPageBean;
import io.github.rowak.nanoleafapi.Panel;
import io.github.rowak.nanoleafapi.ShapeType;

@CCGenClass (expressionBase="#{d.PanelConfigBean}")

public class PanelConfigBean extends DefaultPageBean implements Serializable {
	public void onSave(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
		
		Nlconnect nlconnect = new Nlconnect();
		
		nlconnect.setNchostname("Canvas-72FA.fritz.box");
		nlconnect.setNcipadress("192.168.178.141");
		nlconnect.setNcport(16021);
		nlconnect.setNccountpanel(15);
		nlconnect.setNctoken("LAG28BQWrXK2p79NbHMQsvcYYCN1TcD4");
		nlconnect.setNctype(NanoTypeEnum.CANVAS);
		
		try {
			NlconnectWorker worker = new NlconnectWorker();
			worker.insertNlconnect(nlconnect);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
    public void onLoad(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	
    }

    public void onReset(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	clearAll();
    }

    public void onLayoutFile(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	
    }
    
    private void clearAll() {
    	getPanelInfoListSource().clear();
    	getPaneRepeatList().clear();
    	
    	getPanelIDPanelInfoSourceMap().clear();
    	
    	setAnzahlPanels(1);
    }

    ValidValuesBinding m_layoutFileVV = new ValidValuesBinding();
    public ValidValuesBinding getLayoutFileVV() { return m_layoutFileVV; }

    String m_layoutFile;
    public String getLayoutFile() { return m_layoutFile; }
    public void setLayoutFile(String value) { this.m_layoutFile = value; }

    public void onCheckZurodnung(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	
    	if (getColor() == null || getColor().equals("#000000") || getColor().equals(getDefaultPanelColor())) {
    		OKPopup.createInstance("Start Zuordnung Farbe", "Bitte w�hlen Sie eine Farbe f�r die Zuordnung der Panels.");
    		m_startZuordnung = false;
    		return;
    	} else {
    		selectNextPanel();
        	
    	}
    }
    
    public String getLiteral(String key) {
    	return getLiteral("Nanoleaf", key);
    }
    
    private void selectNextPanel() {
    	if (getPanelInfoListSource().size() > 0) {
    		getPanelInfoListSource().get(0).setColor(getColor());
    	} else {
    		setColor("#000000");
    		m_startZuordnung = false;
    	}
    }

    boolean m_startZuordnung;
    public boolean getStartZuordnung() { return m_startZuordnung; }
    public void setStartZuordnung(boolean value) { this.m_startZuordnung = value; }

    final String m_defaultPanelColor = "#a5a5a5";
    public String getDefaultPanelColor() { return m_defaultPanelColor; }


	
    String m_color = "#000000";
    public String getColor() { return m_color; }
    public void setColor(String value) { this.m_color = value; }

	
    ValidValuesBinding m_colorCombo = new ValidValuesBinding();
    public ValidValuesBinding getColorCombo() { return m_colorCombo; }

	
    
	public void onPanelSourceAction(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
		//System.out.println(event);
		BaseActionEventInvoke actionEvent = (BaseActionEventInvoke) event;
    	
    	System.out.println("SourceAction: " + actionEvent.getSourceReference());
    	
//    	PanelInfo panelInfo = getPanelIDNanoPANENodeSourceMap().get(actionEvent.getSourceReference());
//    	
//    	if (panelInfo != null) {
//    		Panel panel = panelInfo.getPanel();
//    		
//    		System.out.println("PanelID: " + panel.getId());
//    	}
    	
    	
    }

    boolean m_nanoleafConnected = false;
    public boolean getNanoleafConnected() { return m_nanoleafConnected; }
    public void setNanoleafConnected(boolean value) { this.m_nanoleafConnected = value; }

    public void onNanoleafDeconnect(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	boolean deconnected = false;
    	// TODO: Pruefen: Host IP Tocken port
    	
    	try {
    		if (getNanoleafDeviceServer() != null) {
    			deconnected = getNanoleafDeviceServer().deConnectNanoLeaf();
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
    	setNanoleafConnected(false);
    }

    public void onNanoleafConnect(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	boolean connected = false;
    	// TODO: Pruefen: Host IP Tocken port
    	
    	try {
    		m_nanoleafDeviceServer = new NanoleafDeviceServer(getHostname(), getIpAdresse(), getPort(), getNanoleafToken());
        	
        	connected = m_nanoleafDeviceServer.connectNanoLeaf();
        	
        	setAnzahlPanels(m_nanoleafDeviceServer.getNanoLeafPanels().size());
		} catch (Exception e) {
			e.printStackTrace();
		}
    	setNanoleafConnected(true);

    }

	
	private NanoleafDeviceServer m_nanoleafDeviceServer = null;
	public NanoleafDeviceServer getNanoleafDeviceServer() { return m_nanoleafDeviceServer; }


	ROWDYNAMICCONTENTBinding m_dynMatrixPanels = new ROWDYNAMICCONTENTBinding();
    public ROWDYNAMICCONTENTBinding getDynMatrixPanels() { return m_dynMatrixPanels; }

    public void onPanelsOff(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	List<ComponentNode> componentNodes = getDynMatrixPanels().getContentNodes();
    	
    	System.out.println("List: " + componentNodes.size());
    	List<PANENode> paneList = new ArrayList<PANENode>();
    	for (ComponentNode componentNode: componentNodes) {
    		System.out.println(componentNode);
    		if (componentNode instanceof PANENode) {
    			paneList.add((PANENode)componentNode);
    		}
            
    	}
    }

    public void onPanelsOn(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	
    }

    
	String m_nanoleafToken = "LAG28BQWrXK2p79NbHMQsvcYYCN1TcD4";
    public String getNanoleafToken() { return m_nanoleafToken; }
    public void setNanoleafToken(String value) { this.m_nanoleafToken = value; }

    int m_port = 16021;
    public int getPort() { return m_port; }
    public void setPort(int value) { this.m_port = value; }

    String m_ipAdresse = "192.168.178.141";
    public String getIpAdresse() { return m_ipAdresse; }
    public void setIpAdresse(String value) { this.m_ipAdresse = value; }

    String m_hostname = "Canvas-72FA.fritz.box";
    public String getHostname() { return m_hostname; }
    public void setHostname(String value) { this.m_hostname = value; }

//    private List<NanoPANENode> m_nanoPaneNodeList = null;
//    public List<NanoPANENode> getNanoPaneNodeList() {
//    	if (m_nanoPaneNodeList == null) {
//    		m_nanoPaneNodeList = new ArrayList<NanoPANENode>();
//    	}
//		return m_nanoPaneNodeList;
//	}
//    
//    public NanoPANENode getNanoPaneNode(int id) {
//    	return getNanoPaneNodeList().get(id);
//    }
//	
//    DYNAMICCONTENTBinding m_dynPanelList = new DYNAMICCONTENTBinding();
//    public DYNAMICCONTENTBinding getDynPanelList() { return m_dynPanelList; }
    
    

    public void onPanelsCreate(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	List<Panel> panelList = null;
    	if (getNanoleafDeviceServer() != null) {
    		panelList = getNanoleafDeviceServer().getNanoLeafPanels();
    	
    	}
    	
    	getPanelInfoListSource().clear();
    	getPanelIDPanelInfoSourceMap().clear();
    	getPaneRepeatList().clear();
    	
    	createPanelsList(panelList);
    }


	public void onCheckAndCreate(org.eclnt.jsfserver.base.faces.event.ActionEvent event) {
    	
    	getPaneRepeatList().clear();
    	
    	createPanelMatrix(getAnzahlPanels(), getMatrixX(), getMatrixY());
    }

    int m_matrixY = 3;
    public int getMatrixY() { return m_matrixY; }
    public void setMatrixY(int value) { this.m_matrixY = value; }

    int m_matrixX = 3;
    public int getMatrixX() { return m_matrixX; }
    public void setMatrixX(int value) { this.m_matrixX = value; }

    int m_anzahlPanels = 1;
    public int getAnzahlPanels() { return m_anzahlPanels; }
    public void setAnzahlPanels(int value) { this.m_anzahlPanels = value; }
    
    int m_anzahlPanelsMax = 0;
    public int getAnzahlPanelsMax() { return m_anzahlPanelsMax; }
    public void setAnzahlPanelsMax(int value) { this.m_anzahlPanelsMax = value; }

	
    // ------------------------------------------------------------------------
    // inner classes
    // ------------------------------------------------------------------------
    
    /* Listener to the user of the page bean. */
    public interface IListener extends Serializable {
    	
    }
    
    // ------------------------------------------------------------------------
    // members
    // ------------------------------------------------------------------------
    
    private IListener m_listener;
    
    // ------------------------------------------------------------------------
    // constructors & initialization
    // ------------------------------------------------------------------------

    public PanelConfigBean() {
    	initColorCombo();
    	
    }

    private void initColorCombo() {
		
    	for (ColorEnum colorEnum: ColorEnum.values()) {
    		getColorCombo().addValidValue(colorEnum.name(), colorEnum.name());
    	}
		
	}

    Hashtable<String, PanelInfo> m_panelIDPanelInfoSourceMap = null;
	public Hashtable<String, PanelInfo> getPanelIDPanelInfoSourceMap() {
		if (m_panelIDPanelInfoSourceMap == null) {
			m_panelIDPanelInfoSourceMap = new Hashtable<String, PanelInfo>();
		}
		return m_panelIDPanelInfoSourceMap;
	}
	
//	Hashtable<String, PanelInfo> m_panelIDPanelInfoTargetMap = null;
//	public Hashtable<String, PanelInfo> getPanelIDPanelInfoTargetMap() {
//		if (m_panelIDPanelInfoTargetMap == null) {
//			m_panelIDPanelInfoTargetMap = new Hashtable<String, PanelInfo>();
//		}
//		return m_panelIDPanelInfoTargetMap;
//	}

	
//	public NanoPANENode createNanoLeafNanoPANENode(int listNr, Panel panel) {
//		NanoPANENode nanoPANENode = null;
//		PanelInfo panelInfo = new PanelInfo(listNr, panel);
//		Integer panelID = panel.getId();
//		
//		nanoPANENode = new NanoPANENode(panelInfo);
//		nanoPANENode.setActionListener("#{d.PanelConfigBean.onPanelSourceAction}");
//		nanoPANENode.setInvokeevent("click");
//		nanoPANENode.setHeight(60);
//		nanoPANENode.setWidth(60);
//		nanoPANENode.setBorder("left:2;right:2;top:2;bottom:2;color:#ff0000");
//		nanoPANENode.setDragsend("NANOLEAF:" + panelID);
//		nanoPANENode.setReference(panelID.toString());
//		
//		
//		
//		return nanoPANENode;
//	}


	private void createPanelsList(List<Panel> panelList) {
		
		if (panelList != null && panelList.size() > 0) {
			System.out.println("Panels: " + panelList.size());
		} else {
			panelList = new ArrayList<Panel>();
			Panel panel = new Panel(58456, 1, 2, 2, ShapeType.rhythm());
			panelList.add(panel);
			panel = new Panel(43456, 1, 2, 2, ShapeType.rhythm());
			
			panelList.add(panel);
		}
		
		setAnzahlPanels(panelList.size());
    	
    	    	
    	PanelInfo panelInfo = null;
    	int panelnr = 0;
    	for (int p = 0; p < panelList.size(); p++) {
    		Panel panel = panelList.get(p);
    		panelInfo = new PanelInfo(panelnr, panel);
    		panelInfo.setColor(getDefaultPanelColor());
    		
    		panelnr++;

    		getPanelIDPanelInfoSourceMap().put(panelInfo.getPanelNanoleafID()+"", panelInfo);
    		
    		getPanelInfoListSource().add(panelInfo);
    	}
    	
 
		
	}
    
	private void createPanelMatrix(int anzahlPanels, int matrixX, int matrixY) {
		int anzahlPanelMatrix = 0;
    	PanelInfo panelInfo = null;
    	anzahlPanelMatrix = matrixX * matrixY;
    	
    	if (getAnzahlPanels() > anzahlPanelMatrix) {
    		OKPopup.createInstance("Matrix", "Bitte vergr��ern Sie die Matrix.");
    		return;
    	}
    	
    	
    	
    	List<PanelInfo> paneInfoList = null;
    	PaneRepeat paneRepeat = new PaneRepeat();
    	int panelID = 0;
    	
    	
    	for (int x = 0; x < matrixX; x++) {
    		
    		paneInfoList = new ArrayList<PanelInfo>();
    		paneRepeat = new PaneRepeat();
    		
    		for (int y = 0; y < matrixY; y++) {
    			panelInfo = new PanelInfo();
    			panelInfo.setPanelID(panelID);
    			panelInfo.setReference("REF_XY|" + x + "|" + y);
    			panelInfo.setColor(getDefaultPanelColor());
    			panelInfo.setPanelNanoleafID(panelID);
    			
//    			paneInfoTest.setDrangsendSource("#{d.DragDropPaneBean.onDragSendPaneSource}");
    			
    			paneInfoList.add(panelInfo);
    			
    			
    			panelID++;
    		}
    		paneRepeat.setPaneRepeatID(x);
    		paneRepeat.setPanelInfoList(paneInfoList);
    		
    		getPaneRepeatList().add(paneRepeat);
    	}
    	
    	
	}
	
    
    public void onDropPanelActions(ActionEvent event) {
        if (event instanceof BaseActionEventDrop)
        {
        	
            Statusbar.outputSuccess("Drop-Event was processed: " + event.getClass().getName());
            BaseActionEventDrop baed = (BaseActionEventDrop)event;
            String dragInfo = baed.getDragInfo();
            
            System.out.println(baed.getSourceReference());
            
            String ref = baed.getSourceReference();
            
            MatrixInfo matrixInfo = createMatrixInfo(ref);
            
            if (matrixInfo != null) {
                
                if (dragInfo.startsWith("NANOLEAF:"))
                {
                	String nanoLeafID = dragInfo.substring("NANOLEAF:".length());
                	
                	PanelInfo panelInfo = getPanelIDPanelInfoSourceMap().get(nanoLeafID);
                	panelInfo.setColor(getDefaultPanelColor());
                	
                	getPaneRepeatList().get(matrixInfo.getMatrixX()).getPanelInfoList().set(matrixInfo.getMatrixY(), panelInfo);
                	
                	removeNanoLeafFromSource(nanoLeafID);

                	selectNextPanel();
                	
                	System.out.println("Source: " + nanoLeafID);
                	System.out.println("Ziel: ");
                    System.out.println("Drop: " + dragInfo);
                }
            }
            
        }
        else if (event instanceof BaseActionEventInvoke)
        {
            Statusbar.outputSuccess("Cashier Icon was pressed!");
        }
    }
    
    private void removeNanoLeafFromSource(String nanoLeafID) {
		int aktId = 0;
		int nanoID = 0;
		
		nanoID = Integer.parseInt(nanoLeafID);
		
		for (int p = 0; p < getPanelInfoListSource().size(); p++) {
			PanelInfo panelInfo = getPanelInfoListSource().get(p);
			
			if (panelInfo.getPanelNanoleafID() == nanoID) {
				aktId = p;
			}
		}
		
		getPanelInfoListSource().remove(aktId);
		getPanelIDPanelInfoSourceMap().remove(nanoLeafID);
    	
		
	}
	private MatrixInfo createMatrixInfo(String ref) {
		MatrixInfo matrixInfo = null;
		// #{d.PanelConfigBean.paneRepeatList[1].panelInfoList[2].panelID}
		int x = -1;
		int y = -1;
		
		int lastPointStart = 0;
		int lastPointEnde = 0;
		String lastString = "";
		int counterStart = 0;
		int counterEnde = 0;
		
		counterStart = StringUtil.getCountLetter(ref, '[');
		counterEnde = StringUtil.getCountLetter(ref, ']');
		
		if (counterStart == counterEnde) {
			for (int p = 0; p < counterStart; p++) {
				lastPointStart = ref.indexOf("[");
				lastPointEnde = ref.indexOf("]");
				
				if (x == -1) {
					lastString = ref.substring(lastPointStart +1, lastPointEnde);
					
					x = Integer.parseInt(lastString);
					//System.out.println("X: " + x);
				} else {
					lastString = ref.substring(lastPointStart +1, lastPointEnde);
					y = Integer.parseInt(lastString);
					//System.out.println("Y: " + y);
				}
				ref = ref.substring(lastPointEnde +1);
				//System.out.println(ref);
			}
			matrixInfo = new MatrixInfo(x, y);
		}
		return matrixInfo;
	}


	private List<PaneRepeat> m_paneRepeatList = null;
    public List<PaneRepeat> getPaneRepeatList() {
    	if (m_paneRepeatList == null) {
    		m_paneRepeatList = new ArrayList<PaneRepeat>();
    	}
		return m_paneRepeatList;
	}
    
    private List<PanelInfo> m_panelInfoListSource = null;
    public List<PanelInfo> getPanelInfoListSource() {
    	if (m_panelInfoListSource == null) {
    		m_panelInfoListSource = new ArrayList<PanelInfo>();
    	}
		return m_panelInfoListSource;
	}
    
//    private List<PanelInfo> m_panelInfoListTarget = null;
//    public List<PanelInfo> getPanelInfoListTarget() {
//    	if (m_panelInfoListTarget == null) {
//    		m_panelInfoListTarget = new ArrayList<PanelInfo>();
//    	}
//		return m_panelInfoListTarget;
//	}


	/**
     * Inner Class
     */
    
    public class PaneRepeat {
    	private int i_paneRepeatID = 0;
    	private List<PanelInfo> i_panelInfoList = null;
		public int getPaneRepeatID() {
			return i_paneRepeatID;
		}
		public void setPaneRepeatID(int paneRepeatID) {
			i_paneRepeatID = paneRepeatID;
		}
		public List<PanelInfo> getPanelInfoList() {
			return i_panelInfoList;
		}
		public void setPanelInfoList(List<PanelInfo> panelInfoList) {
			i_panelInfoList = panelInfoList;
		}
    	
    	
    	
    }
    
    public class PanelInfo {    
        

        String i_reference;
        public String getReference() { return i_reference; }
        public void setReference(String value) { this.i_reference = value; }

        String i_color;
        public String getColor() { return i_color; }
        public void setColor(String value) { 
        	
        	this.i_color = value;
        	createBorder();
        }

        String i_drangsendSource;
        public String getDrangsendSource() { return i_drangsendSource; }
        public void setDrangsendSource(String value) { this.i_drangsendSource = value; }


    	int m_panelID = 0;
    	int m_panelNanoleafID = 0;
    	int m_panelMatrixPosX = 0;
    	int m_panelMatrixPosY = 0;
    	String m_panelColor = null;
    	boolean m_panelActiv = true;
    	boolean m_panelInit = false;
    	Panel m_panel;
    	String m_border = null;
    	
    	public PanelInfo() {
    		
    	}
    	
    	public void createBorder() {
    		String border = null;
    		if (getColor().equals(getDefaultPanelColor())) {
    			border = "left:1;right:1;top:1;bottom:1;color:" + getColor();
    		} else {
    			border = "left:3;right:3;top:3;bottom:3;color:" + getColor();
    		}
			
			setBorder(border);
		}
    	
    	public PanelInfo(int panelnr, Panel panel) {
    		this.m_panelID = panelnr;
    		this.m_panel = panel;
    		this.m_panelNanoleafID = panel.getId();
    		this.m_panelMatrixPosX = panel.getX();
    		this.m_panelMatrixPosY = panel.getY();
    		this.i_drangsendSource = "NANOLEAF:" + getPanelNanoleafID();
    	}


    	public int getPanelID() {
    		return m_panelID;
    	}
    	public void setPanelID(int panelID) {
    		m_panelID = panelID;
    	}


    	public int getPanelNanoleafID() {
    		return m_panelNanoleafID;
    	}
    	public void setPanelNanoleafID(int panelNanoleafID) {
    		m_panelNanoleafID = panelNanoleafID;
    	}


    	public int getPanelMatrixPosX() {
    		return m_panelMatrixPosX;
    	}
    	public void setPanelMatrixPosX(int panelMatrixPosX) {
    		m_panelMatrixPosX = panelMatrixPosX;
    	}


    	public int getPanelMatrixPosY() {
    		return m_panelMatrixPosY;
    	}
    	public void setPanelMatrixPosY(int panelMatrixPosY) {
    		m_panelMatrixPosY = panelMatrixPosY;
    	}


    	public String getPanelColor() {
    		return m_panelColor;
    	}
    	public void setPanelColor(String panelColor) {
    		m_panelColor = panelColor;
    	}


    	public boolean getPanelActiv() {
    		return m_panelActiv;
    	}
    	public void setPanelActiv(boolean panelActiv) {
    		m_panelActiv = panelActiv;
    	}


    	public boolean getPanelInit() {
    		return m_panelInit;
    	}
    	public void setPanelInit(boolean panelInit) {
    		m_panelInit = panelInit;
    	}

    	public Panel getPanel() {
    		return m_panel;
    	}

		public String getBorder() {
			return m_border;
		}

		public void setBorder(String border) {
			m_border = border;
		}
    	
    	

    }
    
    
    
    @Override
	public String getPageName() { return "/nanoleaf/tools/panelconfig/panelconfig.xml"; }
    @Override
    public String getRootExpressionUsedInPage() { return "#{d.PanelConfigBean}"; }

    // ------------------------------------------------------------------------
    // public usage
    // ------------------------------------------------------------------------

    /* Initialization of the bean. Add any parameter that is required within your scenario. */
    public void prepare(IListener listener)
    {
        m_listener = listener;
    }

    // ------------------------------------------------------------------------
    // private usage
    // ------------------------------------------------------------------------
}
