package template;

import java.awt.AWTEvent;
import java.awt.event.ActionEvent;
import java.util.Random;

import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;

import de.cbse.jeasy.JEDataField;
import de.cbse.jeasy.JEMessage;
import de.cbse.jeasy.JEObject;
import de.cbse.jeasy.JEOptionPane;
import de.cbse.jeasy.JEPanel;
import de.cbse.jeasy.JESimpleParser;
import de.cbse.jeasy.JETable;
import de.cbse.jeasy.JEUtil;
import de.cbse.jexdb.JECollection;
import de.cbse.jexdb.JEDatabase;
import de.cbse.jexdb.JEDatabaseManager;
import de.cbse.jexdb.JEResource;
import de.cbse.jexdb.JEXDBException;

public class CallBackAdresses extends DefaultJECallBack {
	private long actRecord;
	private JETable tblAdress;
	private boolean filter;
	private boolean allReaded;
	JEDatabase database;
	private JEPanel form;
	private long lasttime;
	int record;
	JECollection jeCol;
	private JEDataField adrNo;

	String[][] cities = { { "NewYork", "USA", "10165" }, { "Berlin", "Germany", "14193" }, { "Hamburg", "Germany", "22305" }, { "Atlanta", "USA", "30060" },
			{ "Peking", "Beijing", "100871" }, { "Tokyo", "Japan", "108-0023" }, { "Singapour", "Singapour", "640401" }, { "Nairobi", "Kenya", "00100" },
			{ "Jakarta", "Indonesia", "13570" }, { "London", "England", "EC4R" } };
	String[] fFirstNames = { "Lara", "Lisa", "Monice", "Laura", "Sophie", "Marlene", "Joni", "Clara", "Anette", "Gisel", "Barabara" };
	String[] lastNames = { "Miller", "Brown", "Kensington", "Bauer", "Grant", "Jefferson", "Ashley", "Smith", "Johnson", "Williams", "Jones", "Brown", "Davis",
			"Wilson" };
	String[] mFirstNames = { "Brent", "Georges", "Hans", "Howard", "James", "Jeff", "Jon", "Lara", "Larry", "Lisa", "Michael", "Philip", "Scott", "Peter",
			"Harry" };
	String[] streets = { "Mainroad", "Bakerstreet", "Bahnhofstr", "Armstrong Ave", "Memorial", "Summerset Str", "Berliner Platz", "Belle Champs",
			"Victoria palace" };

	/**
	 * Initialization
	 */
	public CallBackAdresses() {
		JEUtil.registerJECallBack(this, JEIds.PA_ADRMAIN);
		((JTextArea) JEUtil.getJC(JEIds.DF_ADRTEXT).getComponent()).setTabSize(1);
		form = (JEPanel) JEUtil.getJO(JEIds.PA_ADRFORM);
		adrNo = JEUtil.getDF(JEIds.DF_ID);
		database = new JEDatabase("myAdrDataBase");
		tblAdress = JEUtil.getJT(JEIds.TL_ADRESS);
		try {
			JEDatabaseManager.registerDatabase(database);
			jeCol = JEDatabaseManager.getCollection("myAdrDataBase:Adresses");
		} catch (JEXDBException e) {
			GUIUtils.say("Create DataBase", "The JEasy DataBase can't be created on your disk!");
		}
		readAll();
	}

	private void readAll() {
		readAll(null);
	}

	/**
	 * All events from the swing components like menus, buttons, checkboxes,
	 * datafields are send to this callBack.
	 * 
	 * @param e
	 *            the event send by the component
	 * @param id
	 *            the id of the JEObject
	 * @param idParent
	 *            the id of the JEObject where the component was added
	 */
	public void callBack(AWTEvent e, String id) {
		int eid = e.getID();
		if (eid == ActionEvent.ACTION_PERFORMED) {
			//			System.out.println("CallBackAdresses.callBack()" + id);
			if (id.equals(JEIds.BT_AF_TB_CANCEL)) {
				cancel();
			} else if (id.equals(JEIds.BT_AF_TB_DELETE)) {
				delete();
			} else if (id.equals(JEIds.BT_AF_TB_FIRST)) {
				first();
			} else if (id.equals(JEIds.BT_AF_TB_LAST)) {
				last();
			} else if (id.equals(JEIds.BT_AF_TB_NEXT)) {
				next();
			} else if (id.equals(JEIds.BT_AF_TB_PREVIOUS)) {
				previous();
			} else if (id.equals(JEIds.BT_AF_TB_SAVE)) {
				save();
			} else if (id.equals(JEIds.DF_ADRSEARCH)) {
				filter();
			}
		}
	}

	/**
	 * All Selection events from the tblAdressable are send to this callBack.
	 * 
	 * @param e
	 *            the event send by the Table
	 * @param id
	 *            the id of the JEObject
	 * @param lsm
	 *            the id of the JEObject where the component was added
	 */
	public void callBack(ListSelectionEvent e, String id, ListSelectionModel lsm) {
		if (!e.getValueIsAdjusting()) {
			//			System.out.println("JEDefaultJECallBack.callBack() ListSelectionEvent: " + id + "\n" + e);
			//			System.out.println("JEDefaultJECallBack.callBack() ListSelectionEvent: " + id + "\n" + lsm);
			if (!lsm.isSelectionEmpty()) {
				// record = e.getFirstIndex();
				record = tblAdress.getSelectedRow();
				String s = tblAdress.getMessage(record);
				JEUtil.getPA(JEIds.PA_ADRFORM1).clear();
				JEUtil.getPA(JEIds.PA_ADRFORM2).clear();
				JEUtil.getJM(JEIds.MS_ADRFORM).putMessage("" + s + "");
			}
		}
	}

	/**
	 * Input Verifiers will send to this callback
	 * 
	 * @param id
	 *            the id of the JEObject
	 * @param text
	 *            of the input component
	 * @param error
	 */
	public boolean callBackInputVerifier(String id, String text, int error) {
		//		System.out.println("JEDefaultJECallBack.callBack() InputVerifier: " + id + "\n" + text+" Error: "+error);
		if (id.equals(JEIds.DF_ADRSEARCH)) {
			filter();
		}
		if (error != JEObject.NO_INPUT_ERROR) {
			JEOptionPane op;
			switch (error) {
			case JEObject.INPUT_ERROR_LENGTH:
				GUIUtils.say("Validation error", "Maximum length of " + JEUtil.getJD(id).getDataType().getLength() + " exeeded!");
				return false;
			case JEObject.INPUT_ERROR_PARSE:
				GUIUtils.say("Validation error", "Data not valid!");
				return false;
			case JEObject.INPUT_ERROR_DATE:
				GUIUtils.say("Validation error", "Invalid date!");
				return false;
			case JEObject.INPUT_ERROR_TIME:
				GUIUtils.say("Validation error", "Invalid time!");
				return false;
			case JEObject.INPUT_ERROR_RANGE:
				GUIUtils.say("Validation error", "Data out of range!");
				return false;
			case JEObject.INPUT_ERROR_REGULAREXPRESSION:
				GUIUtils.say("Validation error", "Doesn't match regular expression!");
				return false;
			default:
				GUIUtils.say("Validation error", "Input error number : " + error + "!");
				return true;
			}
		}
		return true;
	}

	/**
	 * All events from the TableModel of the tblAdressable are send to this callBack.
	 * 
	 * @param e
	 *            the event send by the TableModel
	 * @param id
	 *            the id of the JEObject
	 */
	public void callBack(TableModelEvent e, String id) {
	// System.out.println("JEDefaultJECallBack.callBack() TableModelEvent: " + id + "\n" + e);
	}

	/**
	 * Cancels editing and clears the form.
	 */
	private void cancel() {
		JEUtil.getPA(JEIds.PA_ADRFORM1).clear();
		JEUtil.getPA(JEIds.PA_ADRFORM2).clear();
	}

	/**
	 * Deletes the record.
	 */
	private void delete() {
		JEResource res;
		try {
			String msg = JEUtil.getJM(JEIds.MS_ADRFORM).getMessage();
			String key = adrNo.getValue();
			int row = getRowByKey(key);
			if (row >= 0) {
				tblAdress.removeRow(row);
				if (row > tblAdress.getRowCount() - 1)
					row--;
				tblAdress.setSelectedRow(row);
				tblAdress.repaint();
			}
			res = jeCol.getResource(key);
			if (res != null)
				jeCol.removeResource(res);
		} catch (JEXDBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Fills the table with generated random addresses.
	 */
	private void fillTable() {
		JEMessage jemTable = JEUtil.getJM(JEIds.MS_ADRTABLE);
		JEMessage jemAdr = JEUtil.getJM(JEIds.MS_ADRFORM);
		for (int i = 0; i < 10; i++) {
			String s = generateAdress();
			JEUtil.getPA(JEIds.PA_ADRFORM1).clear();
			JEUtil.getPA(JEIds.PA_ADRFORM2).clear();
			jemAdr.putMessage(s);
			save();
		}
		tblAdress.repaint();
	}

	/**
	 * Sets a filter.
	 */
	private void filter() {
		String filter = JEUtil.getJD(JEIds.DF_ADRSEARCH).getValue();
		if (filter == null || filter.length() == 0) {
			removeFilter();
		} else
			setFilter(filter);
	}

	/**
	 * Shows only these records containing the filter in any column.
	 * @param filter
	 */
	private void setFilter(String filter) {
		setAllReaded(false);
		readAll(filter);
	}

	private void removeFilter() {
		setAllReaded(false);
		readAll();
	}

	/**
	 * Goto first record.
	 */
	private void first() {
		tblAdress.repaint();
		tblAdress.setSelectedRow(0);
		//		JEResource res;
		//		record = 1;
		//		actRecord = 0;
		//		try {
		//			res = jeCol.getResource(record);
		//			String s = (String) res.getContent();
		//			JEUtil.getJM(JEIds.MS_ADRFORM).putMessage(s);
		//			actRecord = record;
		//		} catch (JEXDBException e) {
		//			// TODO Auto-generated catch block
		//			next();
		//		}
	}

	/**
	 * Generates an address record.
	 * @return
	 */
	private String generateAdress() {
		StringBuffer sb = new StringBuffer();
		Random r = new Random();
		String eMail = "";
		sb.append("");
		sb.append("");
		int rn = r.nextInt(2);
		if (rn == 0) {
			sb.append(JEUtil.tag("SALUTMR", "true"));
			rn = r.nextInt(mFirstNames.length);
			sb.append(JEUtil.tag("FIRSTNAME", mFirstNames[rn]));
			eMail = mFirstNames[rn] + ".";
		} else {
			sb.append(JEUtil.tag("SALUTMRS", "true"));
			rn = r.nextInt(fFirstNames.length);
			sb.append(JEUtil.tag("FIRSTNAME", fFirstNames[rn]));
			eMail = mFirstNames[rn] + ".";
		}
		rn = r.nextInt(lastNames.length);
		sb.append(JEUtil.tag("LASTNAME", lastNames[rn]));
		sb.append(JEUtil.tag("EMAIL", eMail + lastNames[rn] + "@mail.de"));
		rn = r.nextInt(streets.length);
		sb.append(JEUtil.tag("ADDRESS1", streets[rn]));
		sb.append(JEUtil.tag("MOBIL", "01" + r.nextInt(999999999)));
		sb.append(JEUtil.tag("PHONE", "0" + r.nextInt(999999999)));
		rn = r.nextInt(cities.length);
		sb.append(JEUtil.tag("CITY", cities[rn][0]));
		sb.append(JEUtil.tag("COUNTRY", cities[rn][1]));
		sb.append(JEUtil.tag("POSTCODE", cities[rn][2]));
		sb.append("");
		sb.append("");
		return sb.toString();
	}

	/**
	 * Get next unique number
	 * @return
	 */
	private String getNextAdrNo() {
		long time = System.currentTimeMillis();
		if (lasttime >= time)
			time = ++lasttime;
		lasttime = time;
		return "" + time;
	}

	/**
	 * Goto last record.
	 */
	private void last() {
		tblAdress.setSelectedRow(tblAdress.getRowCount() - 1);
	}

	/**
	 * Goto next record
	 */
	private void next() {
		int row = tblAdress.getSelectedRow();
		tblAdress.setSelectedRow(Math.min(row + 1, tblAdress.getRowCount() - 1));
	}

	/**
	 * Goto previous record.
	 */
	private void previous() {
		int row = tblAdress.getSelectedRow();
		if (row > 0)
			tblAdress.setSelectedRow(row - 1);
	}

	/**
	 * Reads all record out the database into the table.
	 */
	private void readAll(String search) {
		if (isAllReaded())
			return;
		clearAll();
		JEResource res;
		try {
			int anzRecords = jeCol.getResourceCount();
			record = 0;
			for (int i = 1; i < anzRecords; i++) {
				try {
					res = jeCol.getResource(++record);
					String s = (String) res.getContent();
					if (search != null) {
						if (s.indexOf(search) > 0)
							tblAdress.addMessage(s);
					} else
						tblAdress.addMessage(s);
				} catch (JEXDBException e) {}
			}
			setAllReaded(true);
		} catch (JEXDBException e) {
			System.out.println("CallBackAdresses.readAll()" + e);
			e.printStackTrace();
		}
	}

	private void clearAll() {
		form.clear();
	}

	/**
	 * Saves a record with data out of the form.
	 */
	private void save() {
		boolean update = true;
		String actAdrNo = "";
		if (adrNo.getText() == null || adrNo.getText().length() <= 0) {
			actAdrNo = getNextAdrNo();
			adrNo.setText(actAdrNo);
			update = false;
		}
		JEResource res;
		try {
			String msg = JEUtil.getJM(JEIds.MS_ADRFORM).getMessage();
			res = jeCol.createResource(adrNo.getValue(), JEResource.XMLResource);
			res.setContent(msg);
			jeCol.storeResource(res);
			if (!update) {
				tblAdress.addMessage(msg);
			} else {
				update(adrNo.getValue(), msg);
			}
			JEUtil.getPA(JEIds.PA_ADRFORM1).clear();
			JEUtil.getPA(JEIds.PA_ADRFORM2).clear();
			int selRow = tblAdress.getSelectedRow();
			tblAdress.repaint();
			tblAdress.setSelectedRow(selRow);
		} catch (JEXDBException e) {
			GUIUtils.say("Create DataBase", "Unable to create a ressource in the database!");
		}
	}

	/**
	 * Updates a record.
	 * @param value
	 * @param msg
	 */
	private void update(String value, String msg) {
		String key = JESimpleParser.getXMLSubString(msg, "ID");
		int row = getRowByKey(key);
		if (row >= 0) {
			tblAdress.addMessage(msg, row);
		}
	}

	/**
	 * Gets the row for the given key.
	 * @param key
	 * @return
	 */
	private int getRowByKey(String key) {
		int col = tblAdress.getColumnNumByJEasyId(JEIds.DF_TLID);
		for (int row = 0; row < tblAdress.getRowCount(); row++) {
			String kvalue = (String) tblAdress.getValueAt(row, col);
			if (kvalue.equals(key)) {
				return row;
			}
		}
		return -1;
	}

	public boolean isFilter() {
		return filter;
	}

	public void setFilter(boolean filter) {
		this.filter = filter;
	}

	public boolean isAllReaded() {
		return allReaded;
	}

	public void setAllReaded(boolean allReaded) {
		this.allReaded = allReaded;
	}
}