package com.hero.objects.skills;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.GenericObject;
import com.hero.ui.dialog.GenericDialog;
import com.hero.ui.dialog.KnowledgeSkillDialog;
import com.hero.util.Constants;
import com.hero.util.XMLUtility;

/**
 * Copyright (c) 2000 - 2005, CompNet Design, Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, is prohibited unless the following conditions are met: 1.
 * Express written consent of CompNet Design, Inc. is obtained by the developer.
 * 2. Redistributions must retain this copyright notice. THIS SOFTWARE IS
 * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * @author CompNet Design, Inc.
 * @version $Revision$
 */

public class KnowledgeSkill extends Skill {

	private static String xmlID = "KNOWLEDGE_SKILL";

	private String groupsDisplay;

	private String groupsType;

	private ArrayList<String> groupsExamples;

	private boolean groupsAvailable;

	private String peopleDisplay;

	private String peopleType;

	private ArrayList<String> peopleExamples;

	private boolean peopleAvailable;

	private String placesDisplay;

	private String placesType;

	private ArrayList<String> placesExamples;

	private boolean placesAvailable;

	private String thingsDisplay;

	private String thingsType;

	private ArrayList<String> thingsExamples;

	private boolean thingsAvailable;

	private String selectedType;

	private String selectedDisplay;

	public KnowledgeSkill(Element template) {
		super(template, KnowledgeSkill.xmlID);
	}

	@Override
	public String getColumn2Output() {
		if (levelsOnly) {
			return getLevelOnlyOutput();
		}
		String ret = getAlias();
		if ((getName() != null) && (getName().trim().length() > 0)) {
			ret = "<i>" + getName() + ":</i>  " + ret;
		}
		if ((getInput() != null) && (getInput().trim().length() > 0)) {
			ret += ": " + getInput();
		}
		if (getSelectedOption() != null) {
			ret += ": " + getSelectedOption().getAlias();
		}
		if (!HeroDesigner.getInstance().getPrefs().useWG()
				&& (getCharacteristicChoices() != null)
				&& (getCharacteristicChoices().size() > 1)
				&& !(getCharacteristic() == Constants.GENERAL)) {
			ret += " ("
					+ Constants.getCharacteristicString(getCharacteristic())
					+ "-based)";
		}
		String adderString = getAdderString();
		if (adderString.trim().length() > 0) {
			ret += " (";
			ret += adderString;
			ret += ")";
		}
		ret += getModifierString();
		if (showRoll) ret += " " + getRoll();
		if ((getEndUsage() > 0)
				&& (GenericObject.findObjectByID(HeroDesigner.getActiveHero()
						.getPowers(), "ENDURANCERESERVE") != null)
				&& (GenericObject.findObjectByID(getAllAssignedModifiers(),
						"ENDRESERVEOREND") == null)
				&& !HeroDesigner.getInstance().getPrefs().useWG()) {
			if (getUseENDReserve()) {
				ret += " (uses END Reserve)";
			} else {
				ret += " (uses Personal END)";
			}
		}
		return ret;
	}

	@Override
	public GenericDialog getDialog(boolean isNew, boolean isPower) {
		return new KnowledgeSkillDialog(this, isNew, isPower);
	}

	@Override
	public ArrayList<String> getExamples() {
		if (getSelectedDisplay().equals(groupsDisplay)) {
			if (groupsExamples.size() > 0) {
				return (ArrayList<String>) groupsExamples.clone();
			}
		} else if (getSelectedDisplay().equals(peopleDisplay)) {
			if (peopleExamples.size() > 0) {
				return (ArrayList<String>) peopleExamples.clone();
			}
		} else if (getSelectedDisplay().equals(placesDisplay)) {
			if (placesExamples.size() > 0) {
				return (ArrayList<String>) placesExamples.clone();
			}
		} else if (getSelectedDisplay().equals(thingsDisplay)) {
			if (groupsExamples.size() > 0) {
				return (ArrayList<String>) thingsExamples.clone();
			}
		}
		return super.getExamples();
	}

	public String getGroupsDisplay() {
		return groupsDisplay;
	}

	public String getGroupsType() {
		return groupsType;
	}

	public String getPeopleDisplay() {
		return peopleDisplay;
	}

	public String getPeopleType() {
		return peopleType;
	}

	public String getPlacesDisplay() {
		return placesDisplay;
	}

	public String getPlacesType() {
		return placesType;
	}

	@Override
	public Element getSaveXML() {
		Element root = super.getSaveXML();
		root.setAttribute("TYPE", getSelectedDisplay());
		return root;
	}

	public String getSelectedDisplay() {
		return selectedDisplay;
	}

	/**
	 * What type of Knowledge Skill this is (people, places, groups, things)
	 * 
	 * @return
	 */
	public String getSelectedType() {
		if (selectedType == null) {
			selectedType = getGroupsType();
		}
		return selectedType;
	}

	public String getThingsDisplay() {
		return thingsDisplay;
	}

	public String getThingsType() {
		return thingsType;
	}

	/**
	 * The available types (typically "people, places, groups, things")
	 */
	@Override
	public ArrayList<String> getTypes() {
		ArrayList<String> vec = new ArrayList<String>();
		vec.add(getSelectedType());
		if (GenericObject.findObjectByID(getAllAssignedModifiers(), "UOO") != null) {
			GenericObject uoo = GenericObject.findObjectByID(
					getAllAssignedModifiers(), "UOO");
			if ((uoo.getSelectedOption() != null)
					&& uoo.getSelectedOption().getXMLID().equals("UAA")) {
				vec.add("ATTACK");
			}
		}
		return vec;
	}

	@Override
	protected void init(Element element) {
		groupsDisplay = "Groups";
		groupsType = "KNOWLEDGE";
		groupsAvailable = true;
		peopleDisplay = "People";
		peopleType = "AREA";
		peopleAvailable = true;
		placesDisplay = "Places";
		placesType = "AREA";
		placesAvailable = true;
		thingsDisplay = "City";
		thingsType = "AREA";
		thingsAvailable = true;

		selectedType = "KNOWLEDGE";
		selectedDisplay = "Groups";
		characteristic = Constants.GENERAL;
		display = "Knowledge Skill";
		alias = "KS";
		baseCost = 2;
		levelCost = 1;
		levelValue = 1;
		minimumCost = 1;
		minimumLevel = 8;
		super.init(element);
		Element check = element.getChild("GROUPS");
		if (check != null) {
			groupsAvailable = true;
			String check2 = XMLUtility.getValue(check, "DISPLAY");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				groupsDisplay = check2;
			}
			check2 = XMLUtility.getValue(check, "TYPE");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				groupsType = check2;
			}
			List examples = check.getChildren("EXAMPLE");
			groupsExamples = new ArrayList<String>();
			if (examples != null) {
				for (int i = 0; i < examples.size(); i++) {
					Element ex = (Element) examples.get(i);
					if (ex.getTextTrim().length() > 0) {
						boolean add = true;
						if (ex.getChildren("SOURCE") != null && ex.getChildren("SOURCE").size()>0) {
							add = false;
							Iterator iter = ex.getChildren("SOURCE").iterator();
							
							INNER: while (iter.hasNext()) {
								Element s = (Element) iter.next();
								if (!GenericObject.getAllSources().contains(
										s.getTextTrim())) {
									GenericObject.getAllSources().add(
											s.getTextTrim());
								}
								if (HeroDesigner.getInstance().getPrefs()
										.getSources().contains(s.getTextTrim())) {
									add = true;
									break INNER;
								}
							}
						}
						if (add) {
							groupsExamples.add(ex.getTextTrim());
						}
					}

				}
			}
		} else {
			groupsAvailable = false;
		}
		check = element.getChild("PEOPLE");
		if (check != null) {
			peopleAvailable = true;
			String check2 = XMLUtility.getValue(check, "DISPLAY");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				peopleDisplay = check2;
			}
			check2 = XMLUtility.getValue(check, "TYPE");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				peopleType = check2;
			}
			List examples = check.getChildren("EXAMPLE");
			peopleExamples = new ArrayList<String>();
			if (examples != null) {
				for (int i = 0; i < examples.size(); i++) {
					Element ex = (Element) examples.get(i);
					if (ex.getTextTrim().length() > 0) {
						boolean add = true;
						if (ex.getChildren("SOURCE") != null && ex.getChildren("SOURCE").size()>0) {
							add = false;
							Iterator iter = ex.getChildren("SOURCE").iterator();
							INNER: while (iter.hasNext()) {
								Element s = (Element) iter.next();
								if (!GenericObject.getAllSources().contains(
										s.getTextTrim())) {
									GenericObject.getAllSources().add(
											s.getTextTrim());
								}
								if (HeroDesigner.getInstance().getPrefs()
										.getSources().contains(s.getTextTrim())) {
									add = true;
									break INNER;
								}
							}
						}
						if (add) {
							peopleExamples.add(ex.getTextTrim());
						}
					}
				}
			}
		} else {
			peopleAvailable = false;
		}
		check = element.getChild("PLACES");
		if (check != null) {
			placesAvailable = true;
			String check2 = XMLUtility.getValue(check, "DISPLAY");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				placesDisplay = check2;
			}
			check2 = XMLUtility.getValue(check, "TYPE");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				placesType = check2;
			}
			List examples = check.getChildren("EXAMPLE");
			placesExamples = new ArrayList<String>();
			if (examples != null) {
				for (int i = 0; i < examples.size(); i++) {
					Element ex = (Element) examples.get(i);
					if (ex.getTextTrim().length() > 0) {
						boolean add = true;
						if (ex.getChildren("SOURCE") != null && ex.getChildren("SOURCE").size()>0) {
							add = false;
							Iterator iter = ex.getChildren("SOURCE").iterator();
							INNER: while (iter.hasNext()) {
								Element s = (Element) iter.next();
								if (!GenericObject.getAllSources().contains(
										s.getTextTrim())) {
									GenericObject.getAllSources().add(
											s.getTextTrim());
								}
								if (HeroDesigner.getInstance().getPrefs()
										.getSources().contains(s.getTextTrim())) {
									add = true;
									break INNER;
								}
							}
						}
						if (add) {
							placesExamples.add(ex.getTextTrim());
						}
					}
				}
			}
		} else {
			placesAvailable = false;
		}
		check = element.getChild("THINGS");
		if (check != null) {
			thingsAvailable = true;
			String check2 = XMLUtility.getValue(check, "DISPLAY");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				thingsDisplay = check2;
			}
			check2 = XMLUtility.getValue(check, "TYPE");
			if ((check2 != null) && (check2.trim().length() > 0)) {
				thingsType = check2;
			}
			List examples = check.getChildren("EXAMPLE");
			thingsExamples = new ArrayList<String>();
			if (examples != null) {
				for (int i = 0; i < examples.size(); i++) {
					Element ex = (Element) examples.get(i);
					if (ex.getTextTrim().length() > 0) {
						boolean add = true;
						if (ex.getChildren("SOURCE") != null && ex.getChildren("SOURCE").size()>0) {
							add = false;
							Iterator iter = ex.getChildren("SOURCE").iterator();
							INNER: while (iter.hasNext()) {
								Element s = (Element) iter.next();
								if (!GenericObject.getAllSources().contains(
										s.getTextTrim())) {
									GenericObject.getAllSources().add(
											s.getTextTrim());
								}
								if (HeroDesigner.getInstance().getPrefs()
										.getSources().contains(s.getTextTrim())) {
									add = true;
									break INNER;
								}
							}
						}
						if (add) {
							thingsExamples.add(ex.getTextTrim());
						}
					}
				}
			}
		} else {
			thingsAvailable = false;
		}

		if (groupsExamples.size() > 0) {
			Collections.sort(groupsExamples);
		}
		if (peopleExamples.size() > 0) {
			Collections.sort(peopleExamples);
		}
		if (placesExamples.size() > 0) {
			Collections.sort(placesExamples);
		}
		if (thingsExamples.size() > 0) {
			Collections.sort(thingsExamples);
		}
	}

	public boolean isGroupsAvailable() {
		return groupsAvailable;
	}

	public boolean isPeopleAvailable() {
		return peopleAvailable;
	}

	public boolean isPlacesAvailable() {
		return placesAvailable;
	}

	public boolean isThingsAvailable() {
		return thingsAvailable;
	}

	@Override
	public void restoreFromSave(Element root) {
		super.restoreFromSave(root);
		String check = XMLUtility.getValue(root, "TYPE");
		if ((check != null) && (check.trim().length() > 0)) {
			setSelectedTypeByDisplay(check);
		}
	}

	/**
	 * Sets the type of Knowledge Skill by the Display of that type
	 * 
	 * @param type
	 */
	public void setSelectedTypeByDisplay(String type) {

		boolean changeDisplay = false;
		String typeDisplay = getAlias();
		// update the type from old values to new, if necessary...
		if (type.toUpperCase().equals("GROUPS")) {
			type = groupsDisplay;
		} else if (type.toUpperCase().equals("PEOPLE")) {
			type = peopleDisplay;
		} else if (type.toUpperCase().equals("PLACES")) {
			type = placesDisplay;
		} else if (type.toUpperCase().equals("THINGS")) {
			type = groupsDisplay;
		}
		if (getSelectedType().equals(groupsType) && typeDisplay.equals("KS")) {
			changeDisplay = true;
		} else if (getSelectedType().equals(peopleType)
				&& typeDisplay.equals("CuK")) {
			changeDisplay = true;
		} else if (getSelectedType().equals(placesType)
				&& typeDisplay.equals("AK")) {
			changeDisplay = true;
		} else if (getSelectedType().equals(thingsType)
				&& typeDisplay.equals("CK")) {
			changeDisplay = true;
		} else if (typeDisplay.equals(display)) {
			changeDisplay = true;
		}
		selectedDisplay = type;
		if (type.equals(groupsDisplay)) {
			selectedType = groupsType;
			if (changeDisplay) {
				alias = "KS";
				display = "KS";
			}
		} else if (type.equals(peopleDisplay)) {
			selectedType = peopleType;
			if (changeDisplay) {
				alias = "CuK";
				display = "CuK";
			}
		} else if (type.equals(placesDisplay)) {
			selectedType = placesType;
			if (changeDisplay) {
				alias = "AK";
				display = "AK";
			}
		} else if (type.equals(thingsDisplay)) {
			selectedType = thingsType;
			if (changeDisplay) {
				alias = "CK";
				display = "CK";
			}
		}
	}

}