package com.its.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public final class ItsUtils
{
	// 요일유형
	public static final String UNKNOWN_WEEK = "DTW0";
	public static final String MONDAY       = "DTW1";
	public static final String TUESDAY      = "DTW2";
	public static final String WEDNESDAY    = "DTW3";
	public static final String THURSDAY     = "DTW4";
	public static final String FRIDAY       = "DTW5";
	public static final String SATURDAY     = "DTW6";
	public static final String SUNDAY       = "DTW7";

	public static String getCurrFiveMinString() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		int min = cal.get(Calendar.MINUTE);
		cal.add(Calendar.MINUTE, -(min % 5));
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}

	public static Date getPrcsDt(String prcsDt) {
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		Date to = null;
		try {
			to = transFormat.parse(prcsDt);
		} catch (ParseException e) {
			log.error("getPrcsDt: ParseException");
		}
		return to;
	}

	public static String getMissSttsYn(String prcsDt) {

		if (prcsDt == null || prcsDt.length() != 14) {
			return "Y";
		}

		Date startDateTime = getPrcsDt(prcsDt);
		if (startDateTime == null) {
			return "Y";
		}
		Calendar currDateTime = Calendar.getInstance();

		GregorianCalendar gcStartDateTime = new GregorianCalendar();
		GregorianCalendar gcEndDateTime = new GregorianCalendar();
		gcStartDateTime.setTime(startDateTime);
		gcEndDateTime.setTime(currDateTime.getTime());

		long gap = gcEndDateTime.getTimeInMillis() - gcStartDateTime.getTimeInMillis();
		long min = gap / 1000L / 60L;
		return min > 10 ? "Y" : "N";
	}

	public static String getRseCommStts(String prcsDt) {

		if (prcsDt == null || prcsDt.length() != 14) {
			return "CMS1";
		}

		Date startDateTime = getPrcsDt(prcsDt);
		if (startDateTime == null) {
			return "CMS1";
		}
		Calendar currDateTime = Calendar.getInstance();

		GregorianCalendar gcStartDateTime = new GregorianCalendar();
		GregorianCalendar gcEndDateTime = new GregorianCalendar();
		gcStartDateTime.setTime(startDateTime);
		gcEndDateTime.setTime(currDateTime.getTime());

		long gap = gcEndDateTime.getTimeInMillis() - gcStartDateTime.getTimeInMillis();
		long min = gap / 1000L / 60L;
		return min > 30 ? "CMS1" : "CMS0";
	}

	public static String getServiceYn(String prcsDt) {

		if (prcsDt == null || prcsDt.length() != 14) {
			return "N";
		}

		Date startDateTime = getPrcsDt(prcsDt);
		if (startDateTime == null) {
			return "N";
		}
		Calendar currDateTime = Calendar.getInstance();

		GregorianCalendar gcStartDateTime = new GregorianCalendar();
		GregorianCalendar gcEndDateTime = new GregorianCalendar();
		gcStartDateTime.setTime(startDateTime);
		gcEndDateTime.setTime(currDateTime.getTime());

		long gap = gcEndDateTime.getTimeInMillis() - gcStartDateTime.getTimeInMillis();
		long min = gap / 1000L / 60L;
		return min > 10 ? "N" : "Y";
	}

	public static String getMissYn(String prcsDt, String CMTR_GRAD_CD) {

		if (("LTC0").equals(CMTR_GRAD_CD) || ("0").equals(CMTR_GRAD_CD)) {
			return "Y";
		}
		if (prcsDt == null || prcsDt.length() != 14) {
			return "Y";
		}

		Date startDateTime = getPrcsDt(prcsDt);
		if (startDateTime == null) {
			return "Y";
		}
		Calendar currDateTime = Calendar.getInstance();

		GregorianCalendar gcStartDateTime = new GregorianCalendar();
		GregorianCalendar gcEndDateTime = new GregorianCalendar();
		gcStartDateTime.setTime(startDateTime);
		gcEndDateTime.setTime(currDateTime.getTime());

		long gap = gcEndDateTime.getTimeInMillis() - gcStartDateTime.getTimeInMillis();
		long min = gap / 1000L / 60L;
		return min > 10 ? "Y" : "N";
	}
	public static Date stringToDate(String paramTime) {
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		Date to = null;
		try {
			to = transFormat.parse(paramTime);
		} catch (ParseException e) {
			log.error("stringToDate: ParseException");
		}

		return to;
	}

	public static int getDiffMinutes(String fromDt, String toDt) {
		Date dtFrom = stringToDate(fromDt);
		Date dtTo = stringToDate(toDt);
		GregorianCalendar gcFromDt= new GregorianCalendar();
		GregorianCalendar gcToDt = new GregorianCalendar();
		gcFromDt.setTime(dtFrom);
		gcToDt.setTime(dtTo);
		long gap = gcToDt.getTimeInMillis() - gcFromDt.getTimeInMillis();
		long min = gap / 1000L / 60L;
		return (int)min;
	}

	// 0--6: Sunday = 0, C/C++ struct tm, tm_wday
	// 1--7: oracle, SELECT TO_CHAR(SYSDATE, 'D') FROM DUAL;, 주중의 일을 1~7로 표시(일요일이 1)
	//     : java, Calendar cal; cal.get(Calendar.DAY_OF_WEEK, sunday=1, monday=2, ...)
	public static String getDayOfWeek() {
		Date dtNow = new Date();
		int week = getDayWeek(dtNow);
		return getDayOfWeek(week);
	}
	public static String getDayOfWeek(int week) {

		String sWeek = UNKNOWN_WEEK;
		switch(week)
		{
			case 1: sWeek = SUNDAY; 	break;
			case 2: sWeek = MONDAY; 	break;
			case 3: sWeek = TUESDAY; 	break;
			case 4: sWeek = WEDNESDAY; 	break;
			case 5: sWeek = THURSDAY; 	break;
			case 6: sWeek = FRIDAY; 	break;
			case 7: sWeek = SATURDAY; 	break;
		}
		return sWeek;
	}
	public static int getDayWeek(String paramDt) {
		return getDayWeek(stringToDate(paramDt));
	}
	public static int getDayWeek(Date paramDt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(paramDt);
		return cal.get(Calendar.DAY_OF_WEEK);		/* DAY_OF_WEEK 리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다. */
	}

	public static String getFromToday()
	{
		SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
		Date dtNow = new Date();
		return sdfDate.format(dtNow)+"000000";
	}

	public static String getSysTime()
	{
		SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMddHHmmss");
		Date dtNow = new Date();
		return sdfDate.format(dtNow);
	}

	public static String getSysTime(String format)
	{
		SimpleDateFormat sdfDate = new SimpleDateFormat(format);
		Date dtNow = new Date();
		return sdfDate.format(dtNow);
	}
	public static String getSysMonth()
	{
		SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMM");
		Date dtNow = new Date();
		return sdfDate.format(dtNow);
	}
	public static String getSysDay()
	{
		SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
		Date dtNow = new Date();
		return sdfDate.format(dtNow);
	}
	/**
	 * 월 마지막날 가져오기 * @param yyyyMM
	 * @return : yyyyMMdd
	 */
	public static String getLastDayOfMonth(String yyyyMMdd) {

		String year  = yyyyMMdd.substring(0, 4);
		String month = yyyyMMdd.substring(4, 6);

		Calendar cal = Calendar.getInstance();
		cal.set(Integer.parseInt(year), Integer.parseInt(month) - 1, 1);
		String lastDay = year + month + Integer.toString(cal.getActualMaximum(Calendar.DAY_OF_MONTH));

		return lastDay;
	}

	public static void saveByteArrayToFile(String filePath, byte[] byteArrayData) {
		try {
			FileUtils.writeByteArrayToFile(new File(filePath), byteArrayData);
		}
		catch (IOException e) {
			log.error("saveByteArrayToFile: IOException");
		}
	}

	public static byte[] convertBmpToPng(byte[] bmpArrayData) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteArrayInputStream inStream = new ByteArrayInputStream(bmpArrayData);

		try {
			BufferedImage newImage = ImageIO.read(inStream);
			ImageIO.write(newImage, "png", out);
			return out.toByteArray();
		}
		catch (IOException e) {
			log.error("saveByteArrayToFile: IOException");
		}
		finally {
			try {
				out.close();
				inStream.close();
			} catch (IOException e) {
				log.error("saveByteArrayToFile: out close IOException");
			}
		}
		return null;
	}

	public static String createUserDir(String userDir) {

		final String sysDir = System.getProperty("user.dir");
		String createdDir = sysDir + userDir;
		try {
			Path path = Paths.get(createdDir);
			//java.nio.file.Files;
			Files.createDirectories(path);

		}
		catch (IOException e) {
			log.error("createUserDir: IOException");
		}
		return createdDir;
	}
	public static synchronized void saveImageFile(BufferedImage image, String extension, String fullPath)
	{
		try (
			OutputStream out2 = new FileOutputStream(fullPath);
		) {
			ImageIO.write(image, extension, out2);
			out2.close();
			//RenderedImage rendImage = image;
			//ImageIO.write(image, "bmp", new File(fullPath));
		}
		catch (IOException e) {
			log.error("saveImageFile: IOException");
		}
	}

/*
	public static byte[] bitmapToByteArray( Bitmap bitmap ) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream() ;
		bitmap.compress( Bitmap.CompressFormat.PNG, 100, stream) ;
		byte[] byteArray = stream.toByteArray() ;
		return byteArray ;
	}
	public static Bitmap byteArrayToBitmap(byte[] bytearr) {
		return BitmapFactory.decodeByteArray(bytearr, 0, bytearr.length);
	}*/

/**
 * Bitmap bitmap;
 *
 * ByteBuffer buffer= ByteBuffer.Allocate(bitmap.ByteCount);
 * bitmap.copyPixelsToBuffer(buffer);
 * byte[] byteArray = buffer.ToArray<byte>();
 *
 * byte[] byteArray;
 * Bitmap bitmap;
 *
 * int width = 112;
 * int height = 112;
 *
 * bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
 * ByteBuffer buffer = ByteBuffer.wrap(byteArray);
 * buffer.rewind();
 * bitmap.copyPixelsFromBuffer(buffer);
 */

	public static List<String> split(String value, String delim) {

		List<String> list = new ArrayList<String>();

		StringTokenizer stringTokenizer = new StringTokenizer(value, delim);
		while (stringTokenizer.hasMoreTokens()) {
			list.add(stringTokenizer.nextToken().trim());
		}

		return list;
	}

	public static int swapEndian(int x) {
		return swapEndian((short)x) << 16 | swapEndian((short)(x >> 16)) & 0xFFFF;
	}

	public static short swapEndian(short x) {
		return (short)(x << 8 | x >> 8 & 0xFF);
	}


	public static String getHttpServletRemoteIP(HttpServletRequest request) {
		if (request == null) {
			return "";
		}

		String ipAddress = request.getHeader("X-FORWARDED-FOR");
		// proxy 환경일 경우
		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("Proxy-Client-IP");
		}
		// 웹로직 서버일 경우
		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		// 기타
		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getRemoteAddr() ;
		}
		//-Djava.net.preferIPv4Stack=true
		if (ipAddress.equals("0:0:0:0:0:0:0:1"))   //==> ipv6 <== default
		{
			ipAddress = "127.0.0.1";   //==> localhost
		}
		return ipAddress;
	}

//	public static short swap(short x){
//        return (short)((x << 8) | ((x >> 8) & 0xff));
//    }
//	public static char swap(char x){
//        return (char)((x << 8) | ((x >> 8) & 0xff));
//    }
//	public static int swap(int x){
//        return (int)((swap((short)x) << 16) | (swap((short)(x >> 16)) & 0xffff));
//    }
//	public static long swap(long x){
//        return (long)(((long)swap((int)(x)) << 32) | ((long)swap((int)(x >> 32)) & 0xffffffffL));
//    }
//	public static float swap(float x){
//        return Float.intBitsToFloat(swap(Float.floatToRawIntBits(x)));
//    }
//	public static double swap(double x){
//        return Double.longBitsToDouble(swap(Double.doubleToRawLongBits(x)));
//    }

}
