package net.minecraft;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

public class SettingsHandler {
	
	private File out;
	private Boolean cached = false;
	private String resource = null;
	private HashMap<String,String> cache;
	private InputStream input = null;

	public SettingsHandler(String resource, String out) {
		this.resource = resource;
		this.out = new File(out);
	}

	public SettingsHandler(String resource, File out) {
		this.resource = resource;
		this.out = out;
	}
	
	public SettingsHandler(InputStream input, File out) {
		this.input = input;
		this.out = out;
	}
	
	public SettingsHandler(File out) throws FileNotFoundException {
		if (!out.exists()) throw new FileNotFoundException("The out does not exist.");
		this.out = out;
	}
	
	public Boolean isCached() {
		return this.cached;
	}

	public void setCached(Boolean cached) {
		this.cached = cached;
		if (this.cached = false) this.cache = null;
	}
	
	private void create(String resource) {
		InputStream input = getClass().getResourceAsStream(resource);
		if (input != null) {
			FileOutputStream output = null;
			try
			{
				out.getParentFile().mkdirs();
				output = new FileOutputStream(out);
				byte[] buf = new byte[8192];
				int length;

				while ((length = input.read(buf)) > 0) {
					output.write(buf, 0, length);
				}

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					input.close();
				} catch (Exception ignored) {
				}
				try {
					if (output != null)
						output.close();
				}
				catch (Exception ignored)
				{
				}
			}
		}
	}
	
	private void create(InputStream input) {
		if (input != null) {
			FileOutputStream output = null;
			try
			{
				output = new FileOutputStream(out);
				byte[] buf = new byte[8192];
				int length;

				while ((length = input.read(buf)) > 0) {
					output.write(buf, 0, length);
				}

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					input.close();
				} catch (Exception ignored) {
				}
				try {
					if (output != null)
						output.close();
				}
				catch (Exception ignored)
				{
				}
			}
		}
	}
	
	private HashMap<String, String> loadHashMap() {
		HashMap<String,String> result = new HashMap<String,String>();
		
		try {
			BufferedReader br = new BufferedReader(new FileReader(out));
			String line;
			
			while((line = br.readLine()) != null) {
				if ((line.isEmpty()) || (line.startsWith("#")) || (!line.contains(": "))) continue;
				String[] args = line.split(": ");
				if (args.length < 2) {
					result.put(args[0], null);
					continue;
				}
				result.put(args[0], args[1]);
			}
			
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		
		return result;
	}
	
	public void load() {
		if (this.resource != null && !out.exists()) {
			create(resource);
		}
		if (this.input != null && !out.exists()) {
			create(input);
		}
		if (this.cached) {
			this.cache = this.loadHashMap();
		}
		
	}
	
	public String getPropertyString(String property) {
		try {
			if (this.cached) {
				return this.cache.get(property);
			} else {
				HashMap<String,String> contents = this.loadHashMap();
				return contents.get(property);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Integer getPropertyInteger(String property) {
		try {
			if (this.cached) {
				return Integer.parseInt(this.cache.get(property));
			} else {
				HashMap<String,String> contents = this.loadHashMap();
				return Integer.parseInt(contents.get(property));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Boolean getPropertyBoolean(String property) {
		try {
			String result;
			if (this.cached) {
				result = this.cache.get(property);
			} else {
				HashMap<String,String> contents = this.loadHashMap();
				result = contents.get(property);
			}
			if (result != null && result.equalsIgnoreCase("true")) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Double getPropertyDouble(String property) {
		try {
			String result;
			if (this.cached) {
				result = this.cache.get(property);
			} else {
				HashMap<String,String> contents = this.loadHashMap();
				result = contents.get(property);
			}
			if (!result.contains(".")) result += ".0";
			return Double.parseDouble(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Boolean checkProperty(String property) {
		String check;
		try {
			if (this.cached) {
				check = this.cache.get(property);
			} else {
				HashMap<String,String> contents = this.loadHashMap();
				check = contents.get(property);
			}
			if(check != null) return true;
		} catch (Exception e) {
			return false;
		}
		
		return false;
	}
	
	private void flush(HashMap<Integer,String> newContents) {
		try {
			this.delFile(out);
			out.createNewFile();
			BufferedWriter writer = new BufferedWriter(new FileWriter(out));
			for (int i = 1; i <= newContents.size(); i ++) {
				String line = newContents.get(i);
				if (line == null) {
					writer.append("\n");
					continue; 
				}
				writer.append(line);
				writer.append("\n");
			}
			writer.flush();
			writer.close();
			if (cached) this.load();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void delFile(File file) {
		if (file.exists()) {
			//noinspection ResultOfMethodCallIgnored
			file.delete();
		}
	}
	
	private HashMap<Integer,String> getAllFileContents() {
		HashMap<Integer,String> result = new HashMap<Integer,String>();
		Integer i = 1;
		try {
			BufferedReader br = new BufferedReader(new FileReader(out));
			String line;
			
			while((line = br.readLine()) != null) {
				if (line.isEmpty()) {
					result.put(i, null);
					i ++;
					continue;
				}
				
				result.put(i, line);
				i ++;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return result;
	}
	
	public void insertComment(String comment) {
		HashMap<Integer,String> contents = this.getAllFileContents();
		contents.put(contents.size() + 1, "#" + comment);
		this.flush(contents);
	}
	
	public void insertComment(String comment, Integer line) {
		HashMap<Integer,String> contents = this.getAllFileContents();
		if (line >= contents.size() + 1) return;
		HashMap<Integer,String> newContents = new HashMap<Integer,String>();
		for (int i = 1; i < line; i ++) {
			newContents.put(i, contents.get(i));
		}
		newContents.put(line, "#" + comment);
		for (int i = line; i <= contents.size(); i ++) {
			newContents.put(i + 1, contents.get(i));
		}
		this.flush(newContents);
	}
	
	public void put(String property, Object obj) {
		HashMap<Integer,String> contents = this.getAllFileContents();
		contents.put(contents.size() + 1, property + ": " + obj.toString());
		this.flush(contents);
	}
	
	public void put(String property, Object obj, Integer line) {
		HashMap<Integer,String> contents = this.getAllFileContents();
		if (line >= contents.size() + 1) return;
		HashMap<Integer,String> newContents = new HashMap<Integer,String>();
		for (int i = 1; i < line; i ++) {
			newContents.put(i, contents.get(i));
		}
		newContents.put(line, property + ": " + obj.toString());
		for (int i = line; i <= contents.size(); i ++) {
			newContents.put(i + 1, contents.get(i));
		}
		this.flush(newContents);
	}
	
	public void changeProperty(String property, Object obj) {
		HashMap<Integer,String> contents = this.getAllFileContents();
		if ((contents == null)) {
			return;
		}
		for (int i = 1; i <= contents.size(); i ++) {
			if (contents.get(i) == null) continue;
			String check = contents.get(i);
			if (check.startsWith(property)) {
				check = check.replace(property, "");
				if (!(check.startsWith(": "))) continue;
				contents.remove(i);
				contents.put(i, property + ": " + obj.toString());
			}
		}
		this.flush(contents);
	}

	public Integer getLineCount() {
		HashMap<Integer,String> contents = this.getAllFileContents();
		return contents.size();
	}
}


