package smart_gs.logical;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import reasoning_web.logical.Connection;
import reasoning_web.logical.ExplanatoryNote;
import reasoning_web.logical.RWPackage;
import reasoning_web.logical.inter_face.RWElement;
import smart_gs.GSConstants;
import smart_gs.image_search.logical.GSQuery;
import smart_gs.image_search.logical.QueryBucket;
import smart_gs.reasoning_web.URIBearer;
import smart_gs.reasoning_web.desktop.logical.DeskTopFolder;
import smart_gs.reasoning_web.desktop.logical.ShortCut;
import smart_gs.reasoning_web.logical.GSConnection;
import smart_gs.reasoning_web.logical.GS_RWElement;
import smart_gs.reasoning_web.logical.GS_RWPackage;

public class URICreator {
	private static final String ANONYMOUS_USER = URIObject.ANONYMOUS_USER;
	private static String LAST_CREATED_TIME;
	private static int ADDITIONAL_EXTENSION;

	public static final String HEADER = GSConstants.URI_HEADER;
	public static final String SEP1 = URIObject.SEP1;
	public static final String SEP2 = URIObject.SEP2;
	public static final String SEP3 = URIObject.SEP3;
	public static final String SEP4 = URIObject.SEP4;

	public static final String SPREAD_DIRECTORY = URIObject.SPREAD_DIRECTORY;
	public static final String SPREAD = URIObject.SPREAD;
	public static final String REGION = URIObject.REGION;
	public static final String LINE_SEGMENT = URIObject.LINE_SEGMENT;
	public static final String BOOKMARK = URIObject.BOOKMARK;
	public static final String POLYGON = URIObject.POLYGON;
	public static final String RECTANGLE = URIObject.RECTANGLE;
	public static final String MARKER = URIObject.MARKER;
	public static final String LINE = URIObject.LINE;
	public static final String MEMOPAD = URIObject.MEMOPAD;
	public static final String STANDARD_TEXT_DOCUMENT = URIObject.STANDARD_TEXT_DOCUMENT;
	public static final String IDAT = URIObject.IDAT;
	public static final String FIRST_IDAT = URIObject.FIRST_IDAT;
	public static final String SECOND_IDAT = URIObject.SECOND_IDAT;
	public static final String THIRD_IDAT = URIObject.THIRD_IDAT;
	public static final String USERS_NOTE = URIObject.USERS_NOTE;
	public static final String EXPLANATORY_NOTE = URIObject.EXPLANATORY_NOTE;
	public static final String TEXT_SEGMENT = URIObject.TEXT_SEGMENT;
	public static final String CONNECTION = URIObject.CONNECTION;
	public static final String RWPACKAGE = URIObject.RWPACKAGE;
	public static final String GS_RWPACKAGE = URIObject.GS_RWPACKAGE;
	public static final String GSQUERY = URIObject.GSQUERY;
	public static final String SHORTCUT = URIObject.SHORTCUT;
	public static final String BUCKET = URIObject.BUCKET;
	public static final String DESKTOP_FOLDER = URIObject.DESKTOP_FOLDER;
	public static final String USERS_NOTE_DIRECTORY = URIObject.USERS_NOTE_DIRECTORY;
	public static final String ZOMBIE = URIObject.ZOMBIE;
	public static final String ANCHOR = URIObject.ANCHOR;
	public static final String ANCHOR_TEXT_SEGMENT = URIObject.ANCHOR_TEXT_SEGMENT;
	public static final String RESOURCE_BASKET = URIObject.RESOURCE_BASKET;
	public static final String CLOSE_UP_RECTANGLE = URIObject.CLOSE_UP_RECTANGLE;
	
	public static String createURI(RWElement elm) {
		String type = elm.getTypeString();
		String uri = new String();
		if (type.equals(SPREAD_DIRECTORY)) {
			SpreadDirectory directory = (SpreadDirectory)elm;
			if (directory.getParent() == null) {
				uri = HEADER + type + SEP1 + "root" + SEP1 + getURIExtension();
			} else {
				uri = HEADER + getURIWithoutHeaderNorUserNameDatePart(directory.getParent()) 
				+ modifyName(directory.getName()) + SEP1 +getURIExtension();
			}
		} else if (type.equals(USERS_NOTE_DIRECTORY)) {
			UsersNoteDirectory directory = (UsersNoteDirectory)elm;
			if (directory.getParent() == null) {
				uri = HEADER + type + SEP1 + "root" + SEP1 +getURIExtension();
			} else {
				uri = HEADER + getURIWithoutHeaderNorUserNameDatePart(directory.getParent()) 
					+ modifyName(directory.getName()) + SEP1 +getURIExtension();
			}
		} else if (type.equals(SPREAD)) {
			Spread spread = (Spread)elm;
			String fileName = Spread.getFileNameWithoutExtension(spread.getFile());
			String dirURIWithoutHeader = spread.getSpreadDirParent().getURI().substring(HEADER.length());
			uri = HEADER + type + SEP1 + modifyName(fileName) + SEP1 + getURIExtension()
					+ SEP2 + dirURIWithoutHeader;
		} else if (isARegion(type)) {
			Region region = (Region)elm;
			uri = HEADER + type + SEP1 + getURIExtension() + SEP2 
				+ getURIWithoutHeader(region.spread);
		} else if (isAnIDAT(type)) {
			IDAT idat = (IDAT)elm;
			uri = HEADER + type + SEP1 + getURIExtension() +SEP2
				+ getURIWithoutHeader(idat.spread); 
		} else if (type.equals(USERS_NOTE)) {
			UsersNote usersNote = (UsersNote)elm;
			String dir;
			if (usersNote.getUsersNoteDirParent() != null) {
				dir = getURIWithoutHeader(usersNote.getUsersNoteDirParent());
			} else {
				dir = "UNKNOWN_DIRECTORY";
			}
			uri = HEADER + type + SEP1 
				+ modifyName(usersNote.name) + SEP1 + getURIExtension() + SEP2
				+ dir;
		} else if (type.equals(EXPLANATORY_NOTE)) {
			ExplanatoryNote note = (ExplanatoryNote)elm;
			String name = note.getName();
			uri = HEADER + type + SEP1 + modifyName(name) + SEP1 + getURIExtension();
		} else if (type.equals(TEXT_SEGMENT)) {
			TextSegment segment = (TextSegment)elm;
			uri = HEADER + type + SEP1 + getURIExtension();
			if (segment.getDocument() != null) {
				uri += SEP2 + getURIWithoutHeader(segment.getDocument());
			}
		} else if (type.equals(ANCHOR_TEXT_SEGMENT)) {
			AnchorTextSegment segment = (AnchorTextSegment)elm;
			uri = HEADER + type + SEP1 + getURIExtension();
			if (segment.getDocument() != null) {
				uri += SEP2 + getURIWithoutHeader(segment.getDocument());
			}
		} else if (type.equals(CONNECTION)) {
			GSConnection connection = (GSConnection)elm;
			String sourceURI = getURIWithoutHeader(connection.getSourceRWElement());
			String targetURI = getURIWithoutHeader(connection.getTargetRWElement());
			uri = HEADER + type + SEP1 + modifyName(connection.getName()) + SEP1 + getURIExtension() 
				+ SEP3 + sourceURI
				+ SEP4 + targetURI;
		} else if (type.equals(STANDARD_TEXT_DOCUMENT)) {
			uri = HEADER + type + SEP1 + getURIExtension();
		} else if (type.equals(RWPACKAGE)) {
			RWPackage pack = (RWPackage)elm;
			uri = HEADER + type + SEP1 + modifyName(pack.getName()) + SEP1 
				+ getURIExtension();
		} else if (type.equals(GS_RWPACKAGE)) {
			GS_RWPackage pack = (GS_RWPackage)elm;
			uri = HEADER + type + SEP1 + modifyName(pack.getName()) + SEP1 
				+ getURIExtension();
		} else if (type.equals(BUCKET)) {
			uri = HEADER + type + SEP1 + getURIExtension();
		} else if (type.equals(GSQUERY)) {
			GSQuery query = (GSQuery)elm;
			String ext = "";
			if (query.hasSpread()) {
				ext = SEP2 + getURIWithoutHeader(query.getSpread());
			}
			uri = HEADER + type + SEP1 + modifyName(query.getName()) + SEP1
				+ getURIExtension() + ext;
		} else if (type.equals(SHORTCUT)) {
			uri = HEADER + type + SEP1 + getURIExtension();
		} else if (type.equals(DESKTOP_FOLDER)) {
			DeskTopFolder folder = (DeskTopFolder)elm;
			if (folder.getParent() == null) {
				uri = HEADER + type + SEP1 + "root" + SEP1 + getURIExtension();
			} else {
				uri = URIObject.chopLast(folder.getParent().getURI())
					+ modifyName(folder.getName()) + SEP1 +getURIExtension();
			}
		} else if (type.equals(RESOURCE_BASKET)) {
			ResourceBasket resourceBasket = (ResourceBasket)elm;
			uri = HEADER + type +SEP1 + modifyName(resourceBasket.getName()) + SEP1 + getURIExtension(); 
		} else if (type.equals(ZOMBIE)) {
			Zombie zombie = (Zombie)elm;
			String tmp = zombie.getDeadURI();
			String deadURI_toRecord;
			if (tmp.startsWith(HEADER)) {
				deadURI_toRecord = tmp.substring(HEADER.length());
			} else {
				deadURI_toRecord = tmp;
			}
			uri = HEADER + type + SEP1 + getURIExtension() +
				SEP2 + deadURI_toRecord;
			System.out.println(uri);
		} else {
			uri =  "UNKNOWN_URI";
		}

		return uri;
	}
	
	// the returned value ends with '/'
	private static String getURIWithoutHeaderNorUserNameDatePart(SpreadDirectory elem) {
		return auxiliaryMethod01(elem);
	}
	
	// the returned value ends with '/'
	private static String getURIWithoutHeaderNorUserNameDatePart(UsersNoteDirectory elem) {
		return auxiliaryMethod01(elem);
	}
	// the returned value ends with '/'
	private static String auxiliaryMethod01(RWElement elem) {
		String bodyPart = getURIWithoutHeader(elem);
		int lastIndex = bodyPart.length()-1;
		if (bodyPart.charAt(lastIndex) == '/') lastIndex--;
		int answer=lastIndex;
		// first '/' from the right end
		for (int i = lastIndex; i>=0; i--) {
			if (bodyPart.charAt(i) == '/') {
				answer = i;
				break;
			}
		}
		// second '/' from the right end
		for (int i = answer-1; i>=0; i--) {
			if (bodyPart.charAt(i) == '/') {
				answer = i;
				break;
			}
		}
		return bodyPart.substring(0,answer) +  "/";
	}
	


	public static String getURIExtension(){
		String date  = URIObject.getDate();
		String add_ext = additionalExtension(date);
		LAST_CREATED_TIME = date;
		String name = Preference.getInstance().getUserName();
		if (name == null || name == "") {
			return ANONYMOUS_USER +SEP1+ date + add_ext + SEP1;
		} else {
			return modifyName(name) +SEP1+ date + add_ext + SEP1;
		}
	}
	private static String additionalExtension(String created_date) {
		String s = "";
		if (created_date.equals(LAST_CREATED_TIME)) {
			ADDITIONAL_EXTENSION++;
			s = "(" + Integer.toString(ADDITIONAL_EXTENSION) + ")";
		} else {
			ADDITIONAL_EXTENSION = 0;
		}
		return s;
	}
	
	public static final String modifyName(String name) {
		if (name.equals("")) {
			return "UNNAMED";
		} else {
			return name;
		}
	}
	public static final String getURIWithoutHeader(RWElement elm) {
		return elm.getURI().substring(HEADER.length());
	}
	public static Object getOriginalURIWithoutHeader(URIBearer ub) {
		return ub.getOriginalURI().substring(HEADER.length());
	}
	public static final boolean isARegion(String type) {
		return type.equals(RECTANGLE) ||
			type.equals(MARKER) ||
			type.equals(POLYGON) ||
			type.equals(MEMOPAD) ||
			type.equals(BOOKMARK) ||
			type.equals(LINE) ||
			type.endsWith(ANCHOR);
	}
	public static final boolean isAnIDAT(String type) {
		return type.equals(FIRST_IDAT) ||
			type.equals(SECOND_IDAT) ||
			type.equals(THIRD_IDAT);
	}
	
	public static void setURIs(URIBearer ub, String uri, String originalURI) {
		ub.setURI(uri);
		ub.setOriginalURI(originalURI);
	}

}