/*
 *******************************************************************************
 * 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;

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.TableSink {
        private DayPeriodRulesData data;

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

        // Entry point.
        @Override
        public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
            if (key.contentEquals("locales")) {
                return localesSink;
            } else if (key.contentEquals("rules")) {
                return rulesSink;
            }
            return null;
        }

        // Locales.
        private class LocalesSink extends UResource.TableSink {
            @Override
            public void put(UResource.Key key, UResource.Value value) {
                int setNum = parseSetNum(value.getString());
                data.localesToRuleSetNumMap.put(key.toString(), setNum);
            }
        }

        private LocalesSink localesSink = new LocalesSink();

        // Rules.
        private class RulesSink extends UResource.TableSink {
            @Override
            public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
                ruleSetNum = parseSetNum(key.toString());
                data.rules[ruleSetNum] = new DayPeriodRules();
                return ruleSetSink;
            }
        }
        private RulesSink rulesSink = new RulesSink();

        // Rules -> "set10", e.g.
        private class RuleSetSink extends UResource.TableSink {
            @Override
            public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
                period = DayPeriod.fromStringOrNull(key);
                if (period == null) { throw new ICUException("Unknown day period in data."); }
                return periodSink;
            }

            @Override
            public void leave() {
                for (DayPeriod period : data.rules[ruleSetNum].dayPeriodForHour) {
                    if (period == null) {
                        throw new ICUException("Rules in data don't cover all 24 hours (they should).");
                    }
                }
            }
        }
        private RuleSetSink ruleSetSink = new RuleSetSink();

        // Rules -> "set10" -> "morning1", e.g.
        // If multiple times exist in a cutoff (such as before{6:00, 24:00})
        // they'll be sent to the next sink.
        private class PeriodSink extends UResource.TableSink {
            @Override
            public void put(UResource.Key key, UResource.Value value) {
                cutoffType = CutoffType.fromStringOrNull(key);
                addCutoff(cutoffType, value.getString());
            }

            @Override
            public UResource.ArraySink getOrCreateArraySink(UResource.Key key, int initialSize) {
                cutoffType = CutoffType.fromStringOrNull(key);
                return cutoffSink;
            }

            @Override
            public void leave() {
                setDayPeriodForHoursFromCutoffs();
                for (int i = 0; i < cutoffs.length; ++i) {
                    cutoffs[i] = 0;
                }
            }
        }
        private PeriodSink periodSink = new PeriodSink();

        // Rules -> "set10" -> "morning1" -> "before", e.g.
        // Will only enter this sink if more than one time is present for this cutoff.
        private class CutoffSink extends UResource.ArraySink {
            @Override
            public void put(int index, UResource.Value value) {
                addCutoff(cutoffType, value.getString());
            }
        }
        private CutoffSink cutoffSink = new CutoffSink();

        // 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.TableSink {
        private DayPeriodRulesData data;

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

        @Override
        public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
            int setNum = parseSetNum(key.toString());
            if (setNum > data.maxRuleSetNum) {
                data.maxRuleSetNum = setNum;
            }

            return null;
        }
    }

    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)ICUResourceBundle.getBundleInstance(
                ICUResourceBundle.ICU_BASE_NAME,
                "dayPeriods",
                ICUResourceBundle.ICU_DATA_CLASS_LOADER,
                true);

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

        data.rules = new DayPeriodRules[data.maxRuleSetNum + 1];
        DayPeriodRulesDataSink sink = new DayPeriodRulesDataSink(data);
        rb.getAllTableItemsWithFallback("", 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.
    }
}
