// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.util.HashMap;
import java.util.Map;

import com.ibm.icu.util.ICUException;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

public final class DayPeriodRules {
    public enum DayPeriod {
        MIDNIGHT,
        NOON,
        MORNING1,
        AFTERNOON1,
        EVENING1,
        NIGHT1,
        MORNING2,
        AFTERNOON2,
        EVENING2,
        NIGHT2,
        AM,
        PM;

        public static DayPeriod[] VALUES = DayPeriod.values();

        private static DayPeriod fromStringOrNull(CharSequence str) {
            if ("midnight".contentEquals(str)) { return MIDNIGHT; }
            if ("noon".contentEquals(str)) { return NOON; }
            if ("morning1".contentEquals(str)) { return MORNING1; }
            if ("afternoon1".contentEquals(str)) { return AFTERNOON1; }
            if ("evening1".contentEquals(str)) { return EVENING1; }
            if ("night1".contentEquals(str)) { return NIGHT1; }
            if ("morning2".contentEquals(str)) { return MORNING2; }
            if ("afternoon2".contentEquals(str)) { return AFTERNOON2; }
            if ("evening2".contentEquals(str)) { return EVENING2; }
            if ("night2".contentEquals(str)) { return NIGHT2; }
            if ("am".contentEquals(str)) { return AM; }
            if ("pm".contentEquals(str)) { return PM; }
            return null;
        }
    }

    private enum CutoffType {
        BEFORE,
        AFTER,  // TODO: AFTER is deprecated in CLDR 29. Remove.
        FROM,
        AT;

        private static CutoffType fromStringOrNull(CharSequence str) {
            if ("from".contentEquals(str)) { return CutoffType.FROM; }
            if ("before".contentEquals(str)) { return CutoffType.BEFORE; }
            if ("after".contentEquals(str)) { return CutoffType.AFTER; }
            if ("at".contentEquals(str)) { return CutoffType.AT; }
            return null;
        }
    }

    private static final class DayPeriodRulesData {
        Map<String, Integer> localesToRuleSetNumMap = new HashMap<String, Integer>();
        DayPeriodRules[] rules;
        int maxRuleSetNum = -1;
    }

    private static final class DayPeriodRulesDataSink extends UResource.Sink {
        private DayPeriodRulesData data;

        private DayPeriodRulesDataSink(DayPeriodRulesData data) {
            this.data = data;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            UResource.Table dayPeriodData = value.getTable();
            for (int i = 0; dayPeriodData.getKeyAndValue(i, key, value); ++i) {
                if (key.contentEquals("locales")) {
                    UResource.Table locales = value.getTable();
                    for (int j = 0; locales.getKeyAndValue(j, key, value); ++j) {
                        int setNum = parseSetNum(value.getString());
                        data.localesToRuleSetNumMap.put(key.toString(), setNum);
                    }
                } else if (key.contentEquals("rules")) {
                    UResource.Table rules = value.getTable();
                    processRules(rules, key, value);
                }
            }
        }

        private void processRules(UResource.Table rules, UResource.Key key, UResource.Value value) {
            for (int i = 0; rules.getKeyAndValue(i, key, value); ++i) {
                ruleSetNum = parseSetNum(key.toString());
                data.rules[ruleSetNum] = new DayPeriodRules();

                UResource.Table ruleSet = value.getTable();
                for (int j = 0; ruleSet.getKeyAndValue(j, key, value); ++j) {
                    period = DayPeriod.fromStringOrNull(key);
                    if (period == null) { throw new ICUException("Unknown day period in data."); }

                    UResource.Table periodDefinition = value.getTable();
                    for (int k = 0; periodDefinition.getKeyAndValue(k, key, value); ++k) {
                        if (value.getType() == UResourceBundle.STRING) {
                            // Key-value pairs (e.g. before{6:00})
                            CutoffType type = CutoffType.fromStringOrNull(key);
                            addCutoff(type, value.getString());
                        } else {
                            // Arrays (e.g. before{6:00, 24:00}
                            cutoffType = CutoffType.fromStringOrNull(key);
                            UResource.Array cutoffArray = value.getArray();
                            int length = cutoffArray.getSize();
                            for (int l = 0; l < length; ++l) {
                                cutoffArray.getValue(l, value);
                                addCutoff(cutoffType, value.getString());
                            }
                        }
                    }
                    setDayPeriodForHoursFromCutoffs();
                    for (int k = 0; k < cutoffs.length; ++k) {
                        cutoffs[k] = 0;
                    }
                }
                for (DayPeriod period : data.rules[ruleSetNum].dayPeriodForHour) {
                    if (period == null) {
                        throw new ICUException("Rules in data don't cover all 24 hours (they should).");
                    }
                }
            }
        }

        // Members.
        private int cutoffs[] = new int[25];  // [0] thru [24]; 24 is allowed is "before 24".

        // "Path" to data.
        private int ruleSetNum;
        private DayPeriod period;
        private CutoffType cutoffType;

        // Helpers.
        private void addCutoff(CutoffType type, String hourStr) {
            if (type == null) { throw new ICUException("Cutoff type not recognized."); }
            int hour = parseHour(hourStr);
            cutoffs[hour] |= 1 << type.ordinal();
        }

        private void setDayPeriodForHoursFromCutoffs() {
            DayPeriodRules rule = data.rules[ruleSetNum];
            for (int startHour = 0; startHour <= 24; ++startHour) {
                // AT cutoffs must be either midnight or noon.
                if ((cutoffs[startHour] & (1 << CutoffType.AT.ordinal())) > 0) {
                    if (startHour == 0 && period == DayPeriod.MIDNIGHT) {
                        rule.hasMidnight = true;
                    } else if (startHour == 12 && period == DayPeriod.NOON) {
                        rule.hasNoon = true;
                    } else {
                        throw new ICUException("AT cutoff must only be set for 0:00 or 12:00.");
                    }
                }

                // FROM/AFTER and BEFORE must come in a pair.
                if ((cutoffs[startHour] & (1 << CutoffType.FROM.ordinal())) > 0 ||
                        (cutoffs[startHour] & (1 << CutoffType.AFTER.ordinal())) > 0) {
                    for (int hour = startHour + 1;; ++hour) {
                        if (hour == startHour) {
                            // We've gone around the array once and can't find a BEFORE.
                            throw new ICUException(
                                    "FROM/AFTER cutoffs must have a matching BEFORE cutoff.");
                        }
                        if (hour == 25) { hour = 0; }
                        if ((cutoffs[hour] & (1 << CutoffType.BEFORE.ordinal())) > 0) {
                            rule.add(startHour, hour, period);
                            break;
                        }
                    }
                }
            }
        }

        private static int parseHour(String str) {
            int firstColonPos = str.indexOf(':');
            if (firstColonPos < 0 || !str.substring(firstColonPos).equals(":00")) {
                throw new ICUException("Cutoff time must end in \":00\".");
            }

            String hourStr = str.substring(0, firstColonPos);
            if (firstColonPos != 1 && firstColonPos != 2) {
                throw new ICUException("Cutoff time must begin with h: or hh:");
            }

            int hour = Integer.parseInt(hourStr);
            // parseInt() throws NumberFormatException if hourStr isn't proper.

            if (hour < 0 || hour > 24) {
                throw new ICUException("Cutoff hour must be between 0 and 24, inclusive.");
            }

            return hour;
        }
    }  // DayPeriodRulesDataSink

    private static class DayPeriodRulesCountSink extends UResource.Sink {
        private DayPeriodRulesData data;

        private DayPeriodRulesCountSink(DayPeriodRulesData data) {
            this.data = data;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            UResource.Table rules = value.getTable();
            for (int i = 0; rules.getKeyAndValue(i, key, value); ++i) {
                int setNum = parseSetNum(key.toString());
                if (setNum > data.maxRuleSetNum) {
                    data.maxRuleSetNum = setNum;
                }
            }
        }
    }

    private static final DayPeriodRulesData DATA = loadData();

    private boolean hasMidnight;
    private boolean hasNoon;
    private DayPeriod[] dayPeriodForHour;

    private DayPeriodRules() {
        hasMidnight = false;
        hasNoon = false;
        dayPeriodForHour = new DayPeriod[24];
    }

    /**
     * Get a DayPeriodRules object given a locale.
     * If data hasn't been loaded, it will be loaded for all locales at once.
     * @param locale locale for which the DayPeriodRules object is requested.
     * @return a DayPeriodRules object for `locale`.
     */
    public static DayPeriodRules getInstance(ULocale locale) {
        String localeCode = locale.getName();
        if (localeCode.isEmpty()) { localeCode = "root"; }

        Integer ruleSetNum = null;
        while (ruleSetNum == null) {
            ruleSetNum = DATA.localesToRuleSetNumMap.get(localeCode);
            if (ruleSetNum == null) {
                localeCode = ULocale.getFallback(localeCode);
                if (localeCode.isEmpty()) {
                    // Saves a lookup in the map.
                    break;
                }
            } else {
                break;
            }
        }

        if (ruleSetNum == null || DATA.rules[ruleSetNum] == null) {
            // Data doesn't exist for the locale requested.
            return null;
        }

        return DATA.rules[ruleSetNum];
    }

    public double getMidPointForDayPeriod(DayPeriod dayPeriod) {
        int startHour = getStartHourForDayPeriod(dayPeriod);
        int endHour = getEndHourForDayPeriod(dayPeriod);

        double midPoint = (startHour + endHour) / 2.0;

        if (startHour > endHour) {
            // dayPeriod wraps around midnight. Shift midPoint by 12 hours, in the direction that
            // lands it in [0, 24).
            midPoint += 12;
            if (midPoint >= 24) {
                midPoint -= 24;
            }
        }

        return midPoint;
    }

    private static DayPeriodRulesData loadData() {
        DayPeriodRulesData data = new DayPeriodRulesData();
        ICUResourceBundle rb = ICUResourceBundle.getBundleInstance(
                ICUData.ICU_BASE_NAME,
                "dayPeriods",
                ICUResourceBundle.ICU_DATA_CLASS_LOADER,
                true);

        DayPeriodRulesCountSink countSink = new DayPeriodRulesCountSink(data);
        rb.getAllItemsWithFallback("rules", countSink);

        data.rules = new DayPeriodRules[data.maxRuleSetNum + 1];
        DayPeriodRulesDataSink sink = new DayPeriodRulesDataSink(data);
        rb.getAllItemsWithFallback("", sink);

        return data;
    }

    private int getStartHourForDayPeriod(DayPeriod dayPeriod) throws IllegalArgumentException {
        if (dayPeriod == DayPeriod.MIDNIGHT) { return 0; }
        if (dayPeriod == DayPeriod.NOON) { return 12; }

        if (dayPeriodForHour[0] == dayPeriod && dayPeriodForHour[23] == dayPeriod) {
            // dayPeriod wraps around midnight. Start hour is later than end hour.
            for (int i = 22; i >= 1; --i) {
                if (dayPeriodForHour[i] != dayPeriod) {
                    return (i + 1);
                }
            }
        } else {
            for (int i = 0; i <= 23; ++i) {
                if (dayPeriodForHour[i] == dayPeriod) {
                    return i;
                }
            }
        }

        // dayPeriod doesn't exist in rule set; throw exception.
        throw new IllegalArgumentException();
    }

    private int getEndHourForDayPeriod(DayPeriod dayPeriod) {
        if (dayPeriod == DayPeriod.MIDNIGHT) { return 0; }
        if (dayPeriod == DayPeriod.NOON) { return 12; }

        if (dayPeriodForHour[0] == dayPeriod && dayPeriodForHour[23] == dayPeriod) {
            // dayPeriod wraps around midnight. End hour is before start hour.
            for (int i = 1; i <= 22; ++i) {
                if (dayPeriodForHour[i] != dayPeriod) {
                    // i o'clock is when a new period starts, therefore when the old period ends.
                    return i;
                }
            }
        } else {
            for (int i = 23; i >= 0; --i) {
                if (dayPeriodForHour[i] == dayPeriod) {
                    return (i + 1);
                }
            }
        }

        // dayPeriod doesn't exist in rule set; throw exception.
        throw new IllegalArgumentException();
    }

    // Getters.
    public boolean hasMidnight() { return hasMidnight; }
    public boolean hasNoon() { return hasNoon; }
    public DayPeriod getDayPeriodForHour(int hour) { return dayPeriodForHour[hour]; }

    // Helpers.
    private void add(int startHour, int limitHour, DayPeriod period) {
        for (int i = startHour; i != limitHour; ++i) {
            if (i == 24) { i = 0; }
            dayPeriodForHour[i] = period;
        }
    }

    private static int parseSetNum(String setNumStr) {
        if (!setNumStr.startsWith("set")) {
            throw new ICUException("Set number should start with \"set\".");
        }

        String numStr = setNumStr.substring(3);  // e.g. "set17" -> "17"
        return Integer.parseInt(numStr);  // This throws NumberFormatException if numStr isn't a proper number.
    }
}
