/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.timezonepicker;

import android.content.Context;
import android.text.Spannable;
import android.text.Spannable.Factory;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.SparseArray;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
import java.util.TimeZone;

public class TimeZoneInfo implements Comparable<TimeZoneInfo> {
    private static final int GMT_TEXT_COLOR = TimeZonePickerUtils.GMT_TEXT_COLOR;
    private static final int DST_SYMBOL_COLOR = TimeZonePickerUtils.DST_SYMBOL_COLOR;
    private static final char SEPARATOR = ',';
    private static final String TAG = null;
    public static int NUM_OF_TRANSITIONS = 6;
    public static long time = System.currentTimeMillis() / 1000;
    public static boolean is24HourFormat;
    private static final Factory mSpannableFactory = Spannable.Factory.getInstance();

    TimeZone mTz;
    public String mTzId;
    int mRawoffset;
    public int[] mTransitions; // may have trailing 0's.
    public String mCountry;
    public int groupId;
    public String mDisplayName;
    private Time recycledTime = new Time();
    private static StringBuilder mSB = new StringBuilder(50);
    private static Formatter mFormatter = new Formatter(mSB, Locale.getDefault());

    public TimeZoneInfo(TimeZone tz, String country) {
        mTz = tz;
        mTzId = tz.getID();
        mCountry = country;
        mRawoffset = tz.getRawOffset();

        try {
            mTransitions = getTransitions(tz, time);
        } catch (NoSuchFieldException ignored) {
        } catch (IllegalAccessException ignored) {
            ignored.printStackTrace();
        }
    }

    SparseArray<String> mLocalTimeCache = new SparseArray<String>();
    long mLocalTimeCacheReferenceTime = 0;
    static private long mGmtDisplayNameUpdateTime;
    static private SparseArray<CharSequence> mGmtDisplayNameCache =
            new SparseArray<CharSequence>();

    public String getLocalTime(long referenceTime) {
        recycledTime.timezone = TimeZone.getDefault().getID();
        recycledTime.set(referenceTime);

        int currYearDay = recycledTime.year * 366 + recycledTime.yearDay;

        recycledTime.timezone = mTzId;
        recycledTime.set(referenceTime);

        String localTimeStr = null;

        int hourMinute = recycledTime.hour * 60 +
                recycledTime.minute;

        if (mLocalTimeCacheReferenceTime != referenceTime) {
            mLocalTimeCacheReferenceTime = referenceTime;
            mLocalTimeCache.clear();
        } else {
            localTimeStr = mLocalTimeCache.get(hourMinute);
        }

        if (localTimeStr == null) {
            String format = "%I:%M %p";
            if (currYearDay != (recycledTime.year * 366 + recycledTime.yearDay)) {
                if (is24HourFormat) {
                    format = "%b %d %H:%M";
                } else {
                    format = "%b %d %I:%M %p";
                }
            } else if (is24HourFormat) {
                format = "%H:%M";
            }

            // format = "%Y-%m-%d %H:%M";
            localTimeStr = recycledTime.format(format);
            mLocalTimeCache.put(hourMinute, localTimeStr);
        }

        return localTimeStr;
    }

    public int getLocalHr(long referenceTime) {
        recycledTime.timezone = mTzId;
        recycledTime.set(referenceTime);
        return recycledTime.hour;
    }

    public int getNowOffsetMillis() {
        return mTz.getOffset(System.currentTimeMillis());
    }

    /*
     * The method is synchronized because there's one mSB, which is used by
     * mFormatter, per instance. If there are multiple callers for
     * getGmtDisplayName, the output may be mangled.
     */
    public synchronized CharSequence getGmtDisplayName(Context context) {
        // TODO Note: The local time is shown in current time (current GMT
        // offset) which may be different from the time specified by
        // mTimeMillis

        final long nowMinute = System.currentTimeMillis() / DateUtils.MINUTE_IN_MILLIS;
        final long now = nowMinute * DateUtils.MINUTE_IN_MILLIS;
        final int gmtOffset = mTz.getOffset(now);
        int cacheKey;

        boolean hasFutureDST = mTz.useDaylightTime();
        if (hasFutureDST) {
            cacheKey = (int) (gmtOffset + 36 * DateUtils.HOUR_IN_MILLIS);
        } else {
            cacheKey = (int) (gmtOffset - 36 * DateUtils.HOUR_IN_MILLIS);
        }

        CharSequence displayName = null;
        if (mGmtDisplayNameUpdateTime != nowMinute) {
            mGmtDisplayNameUpdateTime = nowMinute;
            mGmtDisplayNameCache.clear();
        } else {
            displayName = mGmtDisplayNameCache.get(cacheKey);
        }

        if (displayName == null) {
            mSB.setLength(0);
            int flags = DateUtils.FORMAT_ABBREV_ALL;
            flags |= DateUtils.FORMAT_SHOW_TIME;
            if (TimeZoneInfo.is24HourFormat) {
                flags |= DateUtils.FORMAT_24HOUR;
            }

            // mFormatter writes to mSB
            DateUtils.formatDateRange(context, mFormatter, now, now, flags, mTzId);
            mSB.append("  ");
            int gmtStart = mSB.length();
            TimeZonePickerUtils.appendGmtOffset(mSB, gmtOffset);
            int gmtEnd = mSB.length();

            int symbolStart = 0;
            int symbolEnd = 0;
            if (hasFutureDST) {
                mSB.append(' ');
                symbolStart = mSB.length();
                mSB.append(TimeZonePickerUtils.getDstSymbol()); // Sun symbol
                symbolEnd = mSB.length();
            }

            // Set the gray colors.
            Spannable spannableText = mSpannableFactory.newSpannable(mSB);
            spannableText.setSpan(new ForegroundColorSpan(GMT_TEXT_COLOR),
                    gmtStart, gmtEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            if (hasFutureDST) {
                spannableText.setSpan(new ForegroundColorSpan(DST_SYMBOL_COLOR),
                        symbolStart, symbolEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            displayName = spannableText;
            mGmtDisplayNameCache.put(cacheKey, displayName);
        }
        return displayName;
    }

    private static int[] getTransitions(TimeZone tz, long time)
            throws IllegalAccessException, NoSuchFieldException {
        Class<?> zoneInfoClass = tz.getClass();
        Field mTransitionsField = zoneInfoClass.getDeclaredField("mTransitions");
        mTransitionsField.setAccessible(true);
        int[] objTransitions = (int[]) mTransitionsField.get(tz);
        int[] transitions = null;
        if (objTransitions.length != 0) {
            transitions = new int[NUM_OF_TRANSITIONS];
            int numOfTransitions = 0;
            for (int i = 0; i < objTransitions.length; ++i) {
                if (objTransitions[i] < time) {
                    continue;
                }
                transitions[numOfTransitions++] = objTransitions[i];
                if (numOfTransitions == NUM_OF_TRANSITIONS) {
                    break;
                }
            }
        }
        return transitions;
    }

    public boolean hasSameRules(TimeZoneInfo tzi) {
        // this.mTz.hasSameRules(tzi.mTz)

        return this.mRawoffset == tzi.mRawoffset
                && Arrays.equals(this.mTransitions, tzi.mTransitions);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();

        final String country = this.mCountry;
        final TimeZone tz = this.mTz;

        sb.append(mTzId);
        sb.append(SEPARATOR);
        sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.LONG));
        sb.append(SEPARATOR);
        sb.append(tz.getDisplayName(false /* daylightTime */, TimeZone.SHORT));
        sb.append(SEPARATOR);
        if (tz.useDaylightTime()) {
            sb.append(tz.getDisplayName(true, TimeZone.LONG));
            sb.append(SEPARATOR);
            sb.append(tz.getDisplayName(true, TimeZone.SHORT));
        } else {
            sb.append(SEPARATOR);
        }
        sb.append(SEPARATOR);
        sb.append(tz.getRawOffset() / 3600000f);
        sb.append(SEPARATOR);
        sb.append(tz.getDSTSavings() / 3600000f);
        sb.append(SEPARATOR);
        sb.append(country);
        sb.append(SEPARATOR);

        // 1-1-2013 noon GMT
        sb.append(getLocalTime(1357041600000L));
        sb.append(SEPARATOR);

        // 3-15-2013 noon GMT
        sb.append(getLocalTime(1363348800000L));
        sb.append(SEPARATOR);

        // 7-1-2013 noon GMT
        sb.append(getLocalTime(1372680000000L));
        sb.append(SEPARATOR);

        // 11-01-2013 noon GMT
        sb.append(getLocalTime(1383307200000L));
        sb.append(SEPARATOR);

        // if (this.mTransitions != null && this.mTransitions.length != 0) {
        // sb.append('"');
        // DateFormat df = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss Z",
        // Locale.US);
        // df.setTimeZone(tz);
        // DateFormat weekdayFormat = new SimpleDateFormat("EEEE", Locale.US);
        // weekdayFormat.setTimeZone(tz);
        // Formatter f = new Formatter(sb);
        // for (int i = 0; i < this.mTransitions.length; ++i) {
        // if (this.mTransitions[i] < time) {
        // continue;
        // }
        //
        // String fromTime = formatTime(df, this.mTransitions[i] - 1);
        // String toTime = formatTime(df, this.mTransitions[i]);
        // f.format("%s -> %s (%d)", fromTime, toTime, this.mTransitions[i]);
        //
        // String weekday = weekdayFormat.format(new Date(1000L *
        // this.mTransitions[i]));
        // if (!weekday.equals("Sunday")) {
        // f.format(" -- %s", weekday);
        // }
        // sb.append("##");
        // }
        // sb.append('"');
        // }
        // sb.append(SEPARATOR);
        sb.append('\n');
        return sb.toString();
    }

    private static String formatTime(DateFormat df, int s) {
        long ms = s * 1000L;
        return df.format(new Date(ms));
    }

    /*
     * Returns a negative integer if this instance is less than the other; a
     * positive integer if this instance is greater than the other; 0 if this
     * instance has the same order as the other.
     */
    @Override
    public int compareTo(TimeZoneInfo other) {
        if (this.getNowOffsetMillis() != other.getNowOffsetMillis()) {
            return (other.getNowOffsetMillis() < this.getNowOffsetMillis()) ? -1 : 1;
        }

        // By country
        if (this.mCountry == null) {
            if (other.mCountry != null) {
                return 1;
            }
        }

        if (other.mCountry == null) {
            return -1;
        } else {
            int diff = this.mCountry.compareTo(other.mCountry);

            if (diff != 0) {
                return diff;
            }
        }

        if (Arrays.equals(this.mTransitions, other.mTransitions)) {
            Log.e(TAG, "Not expected to be comparing tz with the same country, same offset," +
                    " same dst, same transitions:\n" + this.toString() + "\n" + other.toString());
        }

        // Finally diff by display name
        if (mDisplayName != null && other.mDisplayName != null)
            return this.mDisplayName.compareTo(other.mDisplayName);

        return this.mTz.getDisplayName(Locale.getDefault()).compareTo(
                other.mTz.getDisplayName(Locale.getDefault()));

    }
}
