/*
MIT Licence

Copyright 2021 Steven Wooding

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
*/

package slite.lib_java;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Parse
{
	private static final SimpleDateFormat sdfDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static final SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
	private static final SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss");

	private static final SimpleDateFormat sdfDateTimeShort = new SimpleDateFormat("yyyyMMddHHmmss");
	private static final SimpleDateFormat sdfDateShort = new SimpleDateFormat("yyyyMMdd");
	private static final SimpleDateFormat sdfTimeShort = new SimpleDateFormat("HHmmss");

	private static final SimpleDateFormat sdfDateTimeUtc = (SimpleDateFormat)sdfDateTime.clone();
	private static final SimpleDateFormat sdfDateUtc = (SimpleDateFormat)sdfDate.clone();
	private static final SimpleDateFormat sdfTimeUtc = (SimpleDateFormat)sdfTime.clone();

	private static final SimpleDateFormat sdfDateTimeUtcShort = (SimpleDateFormat)sdfDateTimeShort.clone();
	private static final SimpleDateFormat sdfDateUtcShort = (SimpleDateFormat)sdfDateShort.clone();
	private static final SimpleDateFormat sdfTimeUtcShort = (SimpleDateFormat)sdfTimeShort.clone();

	static
	{
		sdfDateTimeUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
		sdfDateUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
		sdfTimeUtc.setTimeZone(TimeZone.getTimeZone("UTC"));

		sdfDateTimeUtcShort.setTimeZone(TimeZone.getTimeZone("UTC"));
		sdfDateUtcShort.setTimeZone(TimeZone.getTimeZone("UTC"));
		sdfTimeUtcShort.setTimeZone(TimeZone.getTimeZone("UTC"));
	}

	public static String formatDateTime(long time) { synchronized (sdfDateTime) {return sdfDateTime.format(new Date(time));}}
	public static String formatDate(long time) { synchronized (sdfDate) {return sdfDate.format(new Date(time));} }
	public static String formatTime(long time) { synchronized (sdfTime) {return sdfTime.format(new Date(time));} }

	public static String formatDateTimeShort(long time) { synchronized (sdfDateTimeShort) {return sdfDateTimeShort.format(new Date(time));}}
	public static String formatDateShort(long time) { synchronized (sdfDateShort) {return sdfDateShort.format(new Date(time));} }
	public static String formatTimeShort(long time) { synchronized (sdfTimeShort) {return sdfTimeShort.format(new Date(time));} }

	public static String formatDateTimeUtc(long time) { synchronized (sdfDateTimeUtc) {return sdfDateTimeUtc.format(new Date(time));}}
	public static String formatDateUtc(long time) { synchronized (sdfDateUtc) {return sdfDateUtc.format(new Date(time));} }
	public static String formatTimeUtc(long time) { synchronized (sdfTimeUtc) {return sdfTimeUtc.format(new Date(time));} }

	public static String formatDateTimeUtcShort(long time) { synchronized (sdfDateTimeUtcShort) {return sdfDateTimeUtcShort.format(new Date(time));}}
	public static String formatDateUtcShort(long time) { synchronized (sdfDateUtcShort) {return sdfDateUtcShort.format(new Date(time));} }
	public static String formatTimeUtcShort(long time) { synchronized (sdfTimeUtcShort) {return sdfTimeUtcShort.format(new Date(time));} }

	public static long parseDate(String time) { try { synchronized (sdfDate) {return sdfDate.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseTime(String time) { try { synchronized (sdfTime) {return sdfTime.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseDateTime(String time)
	{
		if (time.length() == 10) time += " 00:00:00";  // if the time is missing
		if (time.length() == 16) time += ":00";  // if seconds are missing
		try { synchronized (sdfDateTime) {return sdfDateTime.parse(time).getTime();} } catch (Exception e){}; return 0;
	}

	public static long parseDateShort(String time) { try { synchronized (sdfDateShort) {return sdfDateShort.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseTimeShort(String time) { try { synchronized (sdfTimeShort) {return sdfTimeShort.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseDateTimeShort(String time)
	{
		if (time.length() == 8) time += "000000"; // if the time is missing
		if (time.length() == 12) time += "00"; // if seconds are missing
		try { synchronized (sdfDateTimeShort) {return sdfDateTimeShort.parse(time).getTime();} } catch (Exception e){}; return 0;
	}


	public static long parseDateUtc(String time) { try { synchronized (sdfDateUtc) {return sdfDateUtc.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseTimeUtc(String time) { try { synchronized (sdfTimeUtc) {return sdfTimeUtc.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseDateTimeUtc(String time)
	{
		if (time.length() == 10) time += " 00:00:00"; // if the time is missing
		if (time.length() == 16) time += ":00"; // if seconds are missing
		try { synchronized (sdfDateTimeUtc) {return sdfDateTimeUtc.parse(time).getTime();} } catch (Exception e){}; return 0;
	}

	public static long parseDateUtcShort(String time) { try { synchronized (sdfDateUtcShort) {return sdfDateUtcShort.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseTimeUtcShort(String time) { try { synchronized (sdfTimeUtcShort) {return sdfTimeUtcShort.parse(time).getTime();} } catch (Exception e){}; return 0; }
	public static long parseDateTimeUtcShort(String time)
	{
		if (time.length() == 8) time += "000000"; // if the time is missing
		if (time.length() == 12) time += "00"; // if seconds are missing
		try { synchronized (sdfDateTimeUtcShort) {return sdfDateTimeUtcShort.parse(time).getTime();} } catch (Exception e){}; return 0;
	}
	/**
	 * Will read till the end of the input stream and return all bytes read. Will block and wait until the input stream ends
	 */
	public static byte[] toBytes(InputStream in) throws IOException
	{
		var bucket = new ByteArrayOutputStream();
		var read = 0;
		var spoon = new byte[1024];
		while((read = in.read(spoon))>=0) bucket.write(spoon, 0, read);
		var result = bucket.toByteArray();
		bucket.close();
		return result;
	}

	public static String fromFileString(String filePath) throws Exception
	{
		FileInputStream fis = new FileInputStream(filePath);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int read = 0;
		while((read=fis.read(buffer))>-1) baos.write(buffer, 0, read);
		String result = new String(baos.toByteArray());
		baos.close();
		fis.close();
		
		return result;
	}
}