package jp.co.corecorp.s3pdf;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class S3Gadget {
	class Value<T> {
		public T v;
		Value(T val) {
			v = val;
		}
	}
	private String	id = null;
	private int	 	type;
	@SuppressWarnings("rawtypes")
	private Value	val = null;
	private Date	lastSyncTime = null;
	private Date	lastModiTime = null;
	private Date	lastRemoveTime = null;
	private ArrayList<String> tags = null;
	
	public static S3Gadget createFromJSON(JSONObject js) throws S3TypeException {
		SimpleDateFormat dfm = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		S3Gadget g = null;
		try {
			String id = js.getString(SharePDF.GADGET_ID);
			int vt = js.getInt(SharePDF.GADGET_VALUETYPE);
			switch( vt ) {
			case SharePDF.GADGET_INT:
				g = new S3Gadget(id, js.getInt(SharePDF.GADGET_VALUE));
				break;
			case SharePDF.GADGET_FLOAT:
				g = new S3Gadget(id, js.getInt(SharePDF.GADGET_VALUE));
				break;
			case SharePDF.GADGET_DATE:
				g = new S3Gadget(id, dfm.parse(js.getString(SharePDF.GADGET_VALUE)));
				break;
			case SharePDF.GADGET_STRING:
				g = new S3Gadget(id, js.getString(SharePDF.GADGET_VALUE));
				break;
			case SharePDF.GADGET_JSON:
				g = new S3Gadget(id, new JSONObject(js.getString(SharePDF.GADGET_VALUE)));
				break;
			case SharePDF.GADGET_FILE:
				g = new S3Gadget(id, new File(js.getString(SharePDF.GADGET_VALUE)));
				break;
			default:
				throw new S3TypeException("gadget type error");
			}
		} catch (JSONException e) {
			throw new S3TypeException("gadget type error");
		} catch (ParseException e) {
			throw new S3TypeException("gadget type error");
		}

		try {
			if( js.has(SharePDF.GADGET_SYNCTIME) )
				g.setSyncTime(dfm.parse(js.getString(SharePDF.GADGET_SYNCTIME)));
		} catch (JSONException e) {
		} catch (ParseException e) {
			throw new S3TypeException("gadget type error");
		}
		try {
			if( js.has(SharePDF.GADGET_MODIFYTIME))
				g.setModifyTime(dfm.parse(js.getString(SharePDF.GADGET_MODIFYTIME)));
		} catch (JSONException e) {
		} catch (ParseException e) {
			throw new S3TypeException("gadget type error");
		}
		
		if( js.has(SharePDF.GADGET_TAGS)) {
			ArrayList<String> t = new ArrayList<String>();
			try {
				JSONArray arr = js.getJSONArray(SharePDF.GADGET_TAGS);
				int n = arr.length();
				int i;
				for( i = 0; i < n; i++ ) {
					String tag = arr.getString(i);
					if( !tag.isEmpty() ) 
						t.add(tag);
				}
				if( !t.isEmpty() )
					g.tags = t;
			} catch (JSONException e) {
				throw new S3TypeException("gadget type error");
			}
		}
		return g;
	}
	
	public JSONObject saveToJSON() throws S3TypeException {
		SimpleDateFormat dfm = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		JSONObject g = null;
		try {
			g = new JSONObject();
			g.put(SharePDF.GADGET_ID, id);
			g.put(SharePDF.GADGET_VALUETYPE, type);
			switch(type) {
			case SharePDF.GADGET_INT:		g.put(SharePDF.GADGET_VALUE, getIntValue());	break;
			case SharePDF.GADGET_FLOAT:		g.put(SharePDF.GADGET_VALUE, getFloatValue());	break;
			case SharePDF.GADGET_DATE:		g.put(SharePDF.GADGET_VALUE, dfm.format(getDateValue()));	break;
			case SharePDF.GADGET_STRING:	g.put(SharePDF.GADGET_VALUE, getStringValue());	break;
			case SharePDF.GADGET_JSON:		g.put(SharePDF.GADGET_VALUE, getJSONValue().toString());	break;
			case SharePDF.GADGET_FILE:		g.put(SharePDF.GADGET_VALUE, getFileValue().toString());	break;
			default:
				throw new S3TypeException("gadget type error");
			}
			if( lastModiTime != null )
				g.put(SharePDF.GADGET_MODIFYTIME, dfm.format(lastModiTime));
			if( lastSyncTime != null )
				g.put(SharePDF.GADGET_SYNCTIME, dfm.format(lastSyncTime));
			if( tags != null ) {
				int n = tags.size();
				if( n > 0 ) {
					JSONArray arr = new JSONArray();
					int i;
					for( i = 0; i < n; i++ ) {
						arr.put(tags.get(i));
					}
					g.put(SharePDF.GADGET_TAGS, arr);
				}
			}
		} catch (JSONException e) {
			throw new S3TypeException("gadget type error");
		}
		return g;
	}
	
	public S3Gadget(String id) {
		this.id = id;
		this.type = SharePDF.GADGET_EMPTY;
	}
	public S3Gadget(String id, int v) {
		this.id = id;
		this.type = SharePDF.GADGET_INT;
		this.val = new Value<Integer>(v);
	}
	public S3Gadget(String id, double v) {
		this.id = id;
		this.type = SharePDF.GADGET_FLOAT;
		this.val = new Value<Double>(v);
	}
	public S3Gadget(String id, Date v) {
		this.id = id;
		this.type = SharePDF.GADGET_DATE;
		this.val = new Value<Date>(v);
	}
	public S3Gadget(String id, String v) {
		this.id = id;
		this.type = SharePDF.GADGET_STRING;
		this.val = new Value<String>(v);
	}
	public S3Gadget(String id, JSONObject v) {
		this.id = id;
		this.type = SharePDF.GADGET_JSON;
		this.val = new Value<JSONObject>(v);
	}
	public S3Gadget(String id, File v) {
		this.id = id;
		this.type = SharePDF.GADGET_FILE;
		this.val = new Value<File>(v);
	}
	
	public String getId() {
		return id;
	}

	public int getType() {
		return type;
	}
	
	@SuppressWarnings("unchecked")
	public int getIntValue() throws S3TypeException {
		if( type != SharePDF.GADGET_INT )
			throw new S3TypeException("gadget type unmatch");
		return ((Value<Integer>)val).v.intValue();
	}
	
	@SuppressWarnings("unchecked")
	public double getFloatValue() throws S3TypeException {
		if( type != SharePDF.GADGET_INT )
			throw new S3TypeException("gadget type unmatch");
		return ((Value<Double>)val).v.doubleValue();
	}
	
	@SuppressWarnings("unchecked")
	public String getStringValue() throws S3TypeException {
		if( type != SharePDF.GADGET_STRING )
			throw new S3TypeException("gadget type unmatch");
		return ((Value<String>)val).v;
	}
	
	@SuppressWarnings("unchecked")
	public Date getDateValue() throws S3TypeException {
		if( type != SharePDF.GADGET_DATE )
			throw new S3TypeException("gadget type unmatch");
		return ((Value<Date>)val).v;
	}
	
	@SuppressWarnings("unchecked")
	public JSONObject getJSONValue() throws S3TypeException {
		if( type != SharePDF.GADGET_JSON )
			throw new S3TypeException("gadget type unmatch");
		return ((Value<JSONObject>)val).v;
	}
	
	@SuppressWarnings("unchecked")
	public File getFileValue() throws S3TypeException {
		if( type != SharePDF.GADGET_FILE)
			throw new S3TypeException("gadget type unmatch");
		return ((Value<File>)val).v;
	}
	
	public void setSyncTime(Date d) {
		lastSyncTime = d;
	}
	public Date getLastSyncTime() {
		return lastSyncTime;
	}

	public void setModifyTime(Date d) {
		lastModiTime = d;
	}
	public Date getLastModifyTime() {
		return lastModiTime;
	}
	public void setRemoveTime(Date d) {
		lastModiTime = d;
	}
	public Date getLastRemoveTime() {
		return lastRemoveTime;
	}
	public ArrayList<String> getTags() {
		return tags;
	}
	
	public boolean has(String tag) {
		if( tags == null )
			return false;
		int n = tags.size();
		for( int i = 0; i < n; i++ ) {
			if( tags.get(i).equals(tag) ) return true;
		}
		return false;
	}
	
	public void setTag(String tag) {
		if( tags == null ) {
			tags = new ArrayList<String>();
		} else {
			if( has(tag) )
				return;
		}
		tags.add(tag);
	}
	
	public void removeTag(String tag) {
		if( tags == null ) {
			return;
		}
		int n = tags.size();
		for( int i = 0; i < n; i++ ) {
			if( tags.get(i).equals(tag) ) {
				tags.remove(i);
				break;
			}
		}
	}
}
