package com.xhpc.card.utils;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.xhpc.pp.utils.HexUtils;

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

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;

public class CP56Time2a {

    public static final String DATE_FORMAT_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
    public static Date cp56toDate(String hex) {

        byte[] bytes = HexUtils.toBytes(hex);
        int milliseconds = HexUtils.reverseHexInt(hex.substring(0, 4));
        int minutes = bytes[2] & 0x3f;
        int hours = bytes[3] & 0x1f;
        int days = bytes[4] & 0x1f;
        int months = bytes[5] & 0x0f;
        int years = bytes[6] & 0x7f;
        DateTime dt = new DateTime();
        dt.setField(DateField.MILLISECOND, 0);
        dt.setField(DateField.SECOND, milliseconds / 1000);
        dt.setField(DateField.MINUTE, minutes);
        dt.setField(DateField.HOUR_OF_DAY, hours);
        dt.setField(DateField.MONTH, months - 1);
        dt.setField(DateField.DAY_OF_MONTH, days);
        dt.setField(DateField.YEAR, years + 2000);
        return dt.toCalendar().getTime();
    }

    public static String cp56toDateStr(String hex) {

        Date date = cp56toDate(hex);
        return DateTime.of(date).toString(DATE_FORMAT_DATE_TIME);
    }

    public static String cp56toDateTSStr(String hex) {

        byte[] bytes = hex.getBytes();
        int[] infoElements = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            infoElements[i] = bytes[i];
        }
        return TimeScale(infoElements);
    }

    public static String toCp56Hex(Date d) {

        byte[] result = new byte[7];
        Calendar date = Calendar.getInstance();
        date.setTime(d);
        String milliSecond = String.format("%04X", (date.get(Calendar.SECOND) * 1000));
        String reversehilo = milliSecond.substring(2, 4).concat(milliSecond.substring(0, 2));
        result[0] = (byte) date.get(Calendar.MINUTE);
        result[1] = (byte) (date.get(Calendar.HOUR_OF_DAY));
        result[2] = (byte) (date.get(Calendar.DAY_OF_MONTH));
        result[3] = (byte) (date.get(Calendar.MONTH) + 1);
        result[4] = (byte) (date.get(Calendar.YEAR) % 100);
        return reversehilo.concat(HexUtils.toHex(result)).substring(0, 14);
    }

    public static String decode(byte[] b) {

        int year = b[6] & 0x7F;
        int month = b[5] & 0x0F;
        int day = b[4] & 0x1F;
        int week = (b[4] & 0xE0) / 32;
        // int week = (b[4] & 0xE0) >> 5;
        int hour = b[3] & 0x1F;
        int minute = b[2] & 0x3F;
        int second = (b[1] << 8) + b[0];
        String str = "20" + year + "-"
                + String.format("%02d", month) + "-"
                + String.format("%02d", day) + "T"
                + String.format("%02d", hour) + ":"
                + String.format("%02d", minute) + ":"
                + String.format("%02d", second / 1000) + "."
                + String.format("%03d", second % 1000);
        return str;
    }

    public static String encode(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        StringBuilder builder = new StringBuilder();
        String milliSecond = String.format("%04X", (calendar.get(Calendar.SECOND) * 1000) + calendar.get(Calendar.MILLISECOND));
        builder.append(milliSecond, 2, 4);
        builder.append(milliSecond, 0, 2);
        builder.append(String.format("%02X", calendar.get(Calendar.MINUTE) & 0x3F));
        builder.append(String.format("%02X", calendar.get(Calendar.HOUR_OF_DAY) & 0x1F));
        int week = calendar.get(Calendar.DAY_OF_WEEK);
        if (week == Calendar.SUNDAY)
            week = 7;
        else week--;
        builder.append(String.format("%02X", (week << 5) + (calendar.get(Calendar.DAY_OF_MONTH) & 0x1F)));
        builder.append(String.format("%02X", calendar.get(Calendar.MONTH) + 1));
        builder.append(String.format("%02X", calendar.get(Calendar.YEAR) - 2000));
        return builder.toString();
    }

    /**
     * 时标CP56Time2a解析
     *
     * @param b 时标CP56Time2a（长度为7 的int数组）
     * @return 解析结果
     */
    public static String TimeScale(int[] b) {

        StringBuilder result = new StringBuilder();
        int year = b[6] & 0x7F;
        int month = b[5] & 0x0F;
        int day = b[4] & 0x1F;
        int week = (b[4] & 0xE0) / 32;
        int hour = b[3] & 0x1F;
        int minute = b[2] & 0x3F;
        int second = (b[1] << 8) + b[0];
        result.append("20");
        result.append(year).append("-");
        result.append(String.format("%02d", month)).append("-");
        result.append(String.format("%02d", day)).append(" ");
        result.append(hour).append(":").append(minute).append(":");
        result.append(second / 1000 + "." + second % 1000);
        return result.toString();
    }

    private static String TimeScale(byte[] bytes) {

        int[] b = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            b[i] = bytes[i];
        }
        return TimeScale(b);
    }

    /**
     * 时间转16进制字符串
     */
    public static String date2HStr(Date date) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        StringBuilder builder = new StringBuilder();
        String milliSecond = String.format("%04X", (calendar.get(Calendar.SECOND) * 1000) + calendar.get(Calendar.MILLISECOND));
        builder.append(milliSecond, 2, 4);
        builder.append(milliSecond, 0, 2);
        builder.append(String.format("%02X", calendar.get(Calendar.MINUTE) & 0x3F));
        builder.append(String.format("%02X", calendar.get(Calendar.HOUR_OF_DAY) & 0x1F));
        int week = calendar.get(Calendar.DAY_OF_WEEK);
        if (week == Calendar.SUNDAY)
            week = 7;
        else week--;
        builder.append(String.format("%02X", (week << 5) + (calendar.get(Calendar.DAY_OF_MONTH) & 0x1F)));
        builder.append(String.format("%02X", calendar.get(Calendar.MONTH) + 1));
        builder.append(String.format("%02X", calendar.get(Calendar.YEAR) - 2000));
        return builder.toString();
    }

    public static Date toDate(byte[] bytes) {

        int milliseconds1 = bytes[0] < 0 ? 256 + bytes[0] : bytes[0];
        int milliseconds2 = bytes[1] < 0 ? 256 + bytes[1] : bytes[1];
        int milliseconds = milliseconds1 + milliseconds2 * 256;
        // 位于 0011 1111
        int minutes = bytes[2] & 0x3f;
        // 位于 0001 1111
        int hours = bytes[3] & 0x1f;
        // 位于 0000 1111
        int days = bytes[4] & 0x0f;
        // 位于 0001 1111
        int months = bytes[5] & 0x0f;
        // 位于 0111 1111
        int years = bytes[6] & 0x7f;
        final Calendar aTime = Calendar.getInstance();
        aTime.set(Calendar.MILLISECOND, milliseconds);
        aTime.set(Calendar.MINUTE, minutes);
        aTime.set(Calendar.HOUR_OF_DAY, hours);
        aTime.set(Calendar.DAY_OF_MONTH, days);
        aTime.set(Calendar.MONTH, months);
        aTime.set(Calendar.YEAR, years + 2000);
        return aTime.getTime();
    }

    public static byte[] toBytes(Date aDate) {

        byte[] result = new byte[7];
        final Calendar aTime = Calendar.getInstance();
        aTime.setTime(aDate);
        final int milliseconds = aTime.get(Calendar.MILLISECOND);
        result[0] = (byte) (milliseconds % 256);
        result[1] = (byte) (milliseconds / 256);
        result[2] = (byte) aTime.get(Calendar.MINUTE);
        result[3] = (byte) aTime.get(Calendar.HOUR_OF_DAY);
        result[4] = (byte) aTime.get(Calendar.DAY_OF_MONTH);
        result[5] = (byte) aTime.get(Calendar.MONTH);
        result[6] = (byte) (aTime.get(Calendar.YEAR) % 100);
        System.out.println("Year->" + aTime.get(Calendar.YEAR));
        return result;
    }

    private static String getCP56time2a(String hex) {

        return "20" + String.format("%02d", Integer.parseInt(hex.substring(12, 14), 16)) + "-"
                + String.format("%02d", Integer.parseInt(hex.substring(10, 12), 16)) + "-"
                + String.format("%02d", Integer.parseInt(hex.substring(8, 10), 16)) + "T"
                + String.format("%02d", Integer.parseInt(hex.substring(6, 8), 16)) + ":"
                + String.format("%02d", Integer.parseInt(hex.substring(4, 6), 16)) + ":"
                + String.format("%02d", Integer.parseInt(hex.substring(2, 4) + "" + hex.substring(0, 2), 16) / 1000);
    }

    public static void main(String[] args) throws InterruptedException {
//        Date time = Calendar.getInstance().getTime();
//        System.out.println(String.format("--未编码--: %s", time));
//        String hex = toCp56Hex(time);
//        System.out.println("--编码1--:" + hex);
//        System.out.println(HexUtils.toBinaryString("90E223133D0416"));
        System.out.println("--下达1--:" + DateUtil.format(cp56toDate("E880380D170518"), NORM_DATETIME_FORMATTER));
        System.out.println("--下达2--:" + DateUtil.format(cp56toDate("A50F3A0D170518"), NORM_DATETIME_FORMATTER));
//        System.out.println("toCp56Hex = " + toCp56Hex(cp56toDate("C05D0D171F0116")));
////        System.out.println("--下达2--:" + DateUtil.format(cp56toDate(""), NORM_DATETIME_FORMAT));
//        String dateStr = "2017-03-01 22:33:23";
//        Date date = DateUtil.parse(dateStr);
//        Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);
//        System.out.println("--变为--:" + newDate.toString());
//        System.out.println("sudo date " + newDate.getTime());
//        System.out.println("--D0073211110815--:" + DateUtil.format(cp56toDate("D0073211110815"), NORM_DATETIME_FORMAT));
//        System.out.println("--A85B3411110815--:" + DateUtil.format(cp56toDate("A85B3411110815"), NORM_DATETIME_FORMAT));
//        String encode = encode(time);
//        System.out.println(String.format("--编码2--:%s", encode));
//        System.out.println("--解码2--:" + decode(HexUtils.toBytes(encode)));

        String s = cp56toDateStr("81461009200A18");

        System.out.println("-111-变为--:" + s);

        String s1 = cp56toDateStr("1AB42D09200A18");

        System.out.println("-111-变为--:" + s1);
    }

}
