/*
 * Kanji.java
 *
 * Ace Kanji Workout
 * Copyright (C) 2006 Alex Quinn <aquinn@cs.washington.edu>
 * Licensed under GPL v2, http://www.gnu.org/licenses/gpl.html
 *
 * Created: May 31, 2006
 * Author:  Alex Quinn
 */

class Kanji {
	protected String kanjiChar;
	protected int unicode;
	protected int frequency;
	protected String[] onReadings;
	protected String[] kunReadings;
	protected String[] meanings;
	protected String[] examples;
	protected int heisig;
	protected int halpern;
	protected int henshall;
	protected int jlptLevel;
	protected int joyo;
	public static final int NO_FREQUENCY = Integer.MAX_VALUE;

	// Special constructor that omits examples and JLPT.  Those come 
	// from sources other than KanjiDic and may be added to the 
	// object later.
	public Kanji(String kanjiChar, int unicode, int frequency, String[] onReadings, 
					String[] kunReadings, String[] meanings, 
					int heisig, int halpern, int henshall, int joyo) {
		this.kanjiChar = kanjiChar;
		this.frequency = frequency;
		if( frequency==0 ) frequency=Integer.MAX_VALUE; // need to make sure frequencies are sorted properly.
		this.unicode = unicode;
		this.onReadings = onReadings;
		this.kunReadings = kunReadings;
		this.meanings = meanings;
		this.heisig = heisig;
		this.halpern = halpern;
		this.henshall = henshall;
		this.joyo = joyo;
		this.jlptLevel = 0;
		this.examples = new String[0];
	}


	boolean hasHalpern() { return halpern != 0; }
	boolean hasHenshall() { return henshall != 0; }
	boolean hasHeisig() { return heisig != 0; }
	boolean hasFrequency() { return frequency != NO_FREQUENCY; }
	boolean hasJlptLevel() { return jlptLevel > 0; }
	public void setJlptLevel(int jlptLevel) {
		this.jlptLevel = jlptLevel;
	}

	public void addExample(String example) {
		// Since the "examples" data member is a standard array, we
		// have to reallocate it to add a member.  Stupid Java.
		String[] oldExamples = this.examples;
		this.examples = new String[oldExamples.length+1];
		System.arraycopy(oldExamples,0,this.examples,0,oldExamples.length);
		this.examples[this.examples.length] = example;
	}
	
	// General constructor
	public Kanji(String kanjiChar, int unicode, String[] onReadings, 
					String[] kunReadings, String[] meanings, 
					String[] examples, int heisig, int halpern, 
					int henshall, int jlptLevel, int joyo) {
		this.kanjiChar = kanjiChar;
		this.frequency = frequency;
		if( frequency==0 ) frequency=Integer.MAX_VALUE; // need to make sure frequencies are sorted properly.
		this.joyo = joyo;
		this.jlptLevel = jlptLevel;
		this.halpern = halpern;
		this.heisig = heisig;
		this.henshall = henshall;
		this.unicode = unicode;
		this.onReadings = onReadings;
		this.kunReadings = kunReadings;
		this.meanings = meanings;
		this.examples = examples;
	}

	public int getJlptLevel() { return jlptLevel; }
	public int getFrequency() { return frequency; }
	public int getJoyo() { return joyo; }
	public String[] getOnReadings() { return onReadings; }
	public String[] getKunReadings() { return kunReadings; }
	public String[] getMeanings() { return meanings; }
	public String[] getExamples() { return examples; }
	public String getKanjiChar() { return kanjiChar; }
	public boolean isJlptOrJoyo() { return joyo>1 || jlptLevel>1; }

	private static String FIELD_SEPARATOR = "/";

	public String toString() {
		/* The serialized form is one line.  It contains the following fields in that order,
		 * separated by tabs.
		 * - kanjiChar
		 * - frequency
		 * - joyo
		 * - jlptLevel
		 * - halpern
		 * - heisig
		 * - henshall
		 * - unicode
		 * - onReadings  (lumped together, separated by FIELD_SEPARATOR)
		 * - kunReadings (lumped together, separated by FIELD_SEPARATOR)
		 * - meanings    (lumped together, separated by FIELD_SEPARATOR)
		 * - examples    (lumped together, separated by FIELD_SEPARATOR)
		 */
		String onString="",kunString="",meaningsString="",examplesString="";
		if( onReadings!=null && onReadings.length>0 ) {
			for( String s : onReadings )
				onString += FIELD_SEPARATOR+s;
			onString = onString.substring(1);
		}
		if( kunReadings!=null && kunReadings.length>0 ) {
			for( String s : kunReadings )
				kunString += FIELD_SEPARATOR+s;
			kunString = kunString.substring(1);
		}
		if( meanings!=null && meanings.length>0 ) {
			for( String s : meanings )
				meaningsString += FIELD_SEPARATOR+s;
			meaningsString = meaningsString.substring(1);
		}
		if( examples!=null && examples.length>0 ) {
			for( String s : examples )
				examplesString += FIELD_SEPARATOR+s;
			examplesString = examplesString.substring(1);
		}
		return String.format("%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%s\t%s\t%s\t;",
			kanjiChar,
			frequency,
			joyo,
			jlptLevel,
			halpern,
			heisig,
			henshall,
			unicode,
			onString,
			kunString,
			meaningsString,
			examplesString
			);
	}
	public Kanji(String stringForm) {
		String[] parts = stringForm.split("\t");
		this.kanjiChar = parts[0];
		this.frequency = Integer.parseInt(parts[1]);
		if( frequency==0 ) frequency=Integer.MAX_VALUE; // need to make sure frequencies are sorted properly.
		this.joyo = Integer.parseInt(parts[2]);
		this.jlptLevel = Integer.parseInt(parts[3]);
		this.halpern = Integer.parseInt(parts[4]);
		this.heisig = Integer.parseInt(parts[5]);
		this.henshall = Integer.parseInt(parts[6]);
		this.unicode = Integer.parseInt(parts[7]);
		onReadings = parts[8].split(FIELD_SEPARATOR);
		kunReadings = parts[9].split(FIELD_SEPARATOR);
		meanings = parts[10].split(FIELD_SEPARATOR);
		examples = parts[11].split(FIELD_SEPARATOR);
	}

	private String condenseArrayIntoDisplayString(String[] parts) {
		String result = "";
		final String divider = ", ";
		for( String s : parts )
			result += divider+s;
		return result.substring(divider.length());
	}
	public String getKunReadingsString() {
		return condenseArrayIntoDisplayString(kunReadings);
	}
	public String getOnReadingsString() {
		return condenseArrayIntoDisplayString(onReadings);
	}
	public String getMeaningsString() {
		return condenseArrayIntoDisplayString(meanings);
	}
	public String debugString() {
		String onString="",kunString="",meaningString="",exampleString="";
		for( String s : onReadings ) { onString += "/"+s; }  onString += "/";
		for( String s : kunReadings ) { kunString += "/"+s; }  kunString += "/";
		for( String s : meanings ) { meaningString += "/"+s; }  meaningString += "/";
		if(examples==null) {
			exampleString="(no examples)";
		}
		else {
			for( String s : examples ) {
				exampleString += "/"+s;
			}
			exampleString += "/";
		}
		return String.format("%s freq=%d unicode=%d %s %s %s %s heisig=%d halpern=%d henshall=%d jlpt=%d joyo=%d",
			kanjiChar,
			frequency,
			unicode,
			onString,
			kunString,
			meaningString,
			exampleString,
			heisig,
			halpern,
			henshall,
			jlptLevel,
			joyo);
	}
}
