package org.jerrymouse.cc.site.bean;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Transient;

import org.jerrymouse.cc.utils.ResourceBuilder;

@Embeddable
public class Type {
	@Transient
	private static Map<String, String> mimeToType;
	@Transient
	private static Map<String, String> typeToMime;
	@Column
	private String suffix;

	public Type() {
	}

	public Type(String suffix) {
		this.suffix = suffix;
	}

	private synchronized void addMimeTypes(String mime_types) {
		int hashPos = mime_types.indexOf('#');
		if (hashPos != -1) {
			mime_types = mime_types.substring(0, hashPos);
		}
		StringTokenizer tok = new StringTokenizer(mime_types);
		if (!tok.hasMoreTokens()) {
			return;
		}
		String contentType = tok.nextToken();
		String s = null;
		while (tok.hasMoreTokens()) {
			String fileType = tok.nextToken();
			if (s == null) {
				s = fileType;
				mimeToType.put(contentType, s);
			}
			typeToMime.put(fileType, contentType);
		}
	}

	public String getMime() {
		if (getTypeToMime().get(suffix) == null)
			return "application/octet-stream";
		return getTypeToMime().get(suffix);
	}

	public Map<String, String> getMimeToType() {
		if (mimeToType == null) {
			initTypes();
		}
		return mimeToType;
	}

	public String getSuffix() {
		return suffix;
	}

	private String getType() {
		return getMime().substring(0, getMime().indexOf('/'));
	}

	private Map<String, String> getTypeToMime() {
		if (typeToMime == null) {
			initTypes();
		}
		return typeToMime;
	}

	private void initTypes() {
		mimeToType = new HashMap<String, String>();
		typeToMime = new HashMap<String, String>();
		BufferedReader reader;
		try {
			reader = new BufferedReader(new InputStreamReader(ResourceBuilder
					.getResourcesBuilder().load("META-INF/mimetypes")));

			String line;
			while ((line = reader.readLine()) != null) {
				addMimeTypes(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setMime(String mime) {
		suffix = getMimeToType().get(mime);
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public String removeSuffix(String filename) {
		int i = filename.lastIndexOf('.');
		if (i == -1)
			return filename;
		else {
			suffix = filename.substring(i + 1);
			return filename.substring(0, i);
		}
	}

	public String addSuffix(String filename) {
		if (getSuffix() == null)
			return filename;
		return filename + "." + getSuffix();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Type) {
			return equals(((Type) obj).getSuffix());
		} else
			return false;
	}

	@Override
	public int hashCode() {
		return suffix.hashCode();
	}

	public boolean equals(String str) {
		return suffix.equals(str);
	}

	@Override
	public String toString() {
		return getSuffix() + ":" + getMime();
	}

	public static List<Type> createTypes(String[] types) {
		List<Type> ts = new ArrayList<Type>();
		for (String t : types) {
			ts.add(new Type(t));
		}
		return ts;
	}

	public static List<String> toStrings(List<Type> ts) {
		List<String> strings = new ArrayList<String>();
		for (Type t : ts) {
			strings.add(t.getSuffix());
		}
		return strings;
	}

	public boolean belongsTo(Type type) {
		return getType().equals(type.getType());
	}

}
