package edu.fichte.pbi.ide.views;

import java.util.ArrayList;

import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.ViewPart;

import edu.fichte.pbi.vm.storage.EEPROM;
import edu.fichte.pbi.vm.storage.IEEPROMMonitor;

public class EEPROMView extends ViewPart implements IEEPROMMonitor {
	
	public static final String ID = "edu.fichte.pbi.ide.eepromView";

	private Label selected;
	private Label previous;
	
	Label address;
	Label charValue;
	Label binaryValue;
	Label decimalValue;
	ArrayList<Label> allBytes = new ArrayList<Label>(EEPROM.SIZE);
	
	Composite infoView;
	Composite eepromParent;
	Composite eepromViewLabelParent;
	
	private Color writeAccess = new Color(Display.getCurrent(), 0, 255, 0);
	private Color highlighted = new Color(Display.getCurrent(), 255, 191, 0);
//	private Color special = new Color(Display.getCurrent(), 255, 0, 192);

	@Override
	public void createPartControl(Composite parent) {
		//parent element, one element wide
		eepromParent = new Composite(parent, 0);
		eepromParent.setLayout(new GridLayout(1, false));
		
		//make composite for all labels representing the eeprom
		eepromViewLabelParent = new Composite(eepromParent, 0);
		eepromViewLabelParent.setLayout(new GridLayout(16, false));
		
		//create the labels, set them to zero
		allBytes.ensureCapacity(EEPROM.SIZE);
		Label newLabel;
		for (int i = 0; i < EEPROM.SIZE; i++) {
			newLabel = new Label(eepromViewLabelParent, 0);
			newLabel.setText("00");
			newLabel.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseUp(MouseEvent event) {
					super.mouseUp(event);
					
					if (event.getSource() instanceof Label) {
						//mark the label with color /highlighted/
						if (selected != null) {
							selected.setBackground(null);
						}
						Label label = (Label) event.getSource();
						selected = label;
						selected.setBackground(highlighted);
						
						//calc details
						String pos = String.valueOf(allBytes.indexOf(label));
						int value = Integer.parseInt(label.getText(), 16);
						String ascii = String.valueOf((char) value);
						String binary = Integer.toBinaryString(value);
						String decimal = String.valueOf(value);
						
						//set new values
						address.setText("Address: " + pos);
						charValue.setText("ASCII: " + ascii);
						binaryValue.setText("Binary: " + binary);
						decimalValue.setText("Decimal: " + decimal);
						
						//update composite
						infoView.pack();
						
					}
				}
			});
			allBytes.add(i, newLabel);
		}
		
		//initialize infoView Composite and labels
		infoView = new Composite(eepromParent, 0);
		infoView.setLayout(new GridLayout(4, false));
		
		address = new Label(infoView, 0);
		charValue = new Label(infoView, 0);
		binaryValue = new Label(infoView, 0);
		decimalValue = new Label(infoView, 0);
		
		address.setText("Address: --");
		charValue.setText("ASCII: --");
		binaryValue.setText("Binary: --");
		decimalValue.setText("Decimal: --");
		
	}


	@Override
	public void update(final String s) {
		getSite().getShell().getDisplay().asyncExec(new Runnable() {

			@Override
			public void run() {
				int value;
				String text;
				String tooltip;
				String[] newBytes = splitIntoParts(s, 2);
				for (int i = 0; i < EEPROM.SIZE; i++) {
					text = newBytes[i].toUpperCase();
					if (!allBytes.get(i).getText().equals(text)) {
						value = Integer.parseInt(text, 16);
						if (allBytes.get(i).equals(selected)) {
							//selected got updated, recalc details
							String ascii = String.valueOf((char) value);
							String binary = Integer.toBinaryString(value);
							String decimal = String.valueOf(value);
							
							//set new values
							charValue.setText("ASCII: " + ascii);
							binaryValue.setText("Binary: " + binary);
							decimalValue.setText("Decimal: " + decimal);
							
							//update composite
							infoView.pack();
						} else {
							allBytes.get(i).setBackground(writeAccess);
						}
						tooltip = "Ascii: "	+ String.valueOf((char) value);
						allBytes.get(i).setToolTipText(tooltip);
					}
					allBytes.get(i).setText(text);
					allBytes.get(i).pack();
					if (previous != selected) {
						previous.setBackground(null);
					}
					previous = allBytes.get(i);
				}
			}
		});
	}


	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
		
	}
	
	private static String[] splitIntoParts(String string, int partSize) {
		int size = Integer.valueOf((int) string.length() / partSize);
		String[] parts = new String[size + 1];
		for (int i = 0; i <= string.length(); i+=partSize) {
			parts[(int) i/partSize] = string.substring(i, Math.min(2*size, i + partSize));
		}
		return parts;
	}

}
