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

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import com.ibm.icu.impl.Grego;
import com.ibm.icu.impl.jdkadapter.TimeZoneICU;
import com.ibm.icu.util.ULocale;

/**
 * TimeZoneJDK is an adapter class which wraps java.util.TimeZone and
 * implements ICU4J TimeZone APIs.
 */
public class TimeZoneJDK extends com.ibm.icu.util.TimeZone {

    private static final long serialVersionUID = -1137052823551791933L;

    private TimeZone fJdkTz;
    private transient Calendar fJdkCal;
    private static Method mObservesDaylightTime;

    static {
        try {
            mObservesDaylightTime = TimeZone.class.getMethod("observesDaylightTime", (Class[]) null);
        } catch (NoSuchMethodException e) {
            // Java 6 or older
        } catch (SecurityException e) {
            // not visible
        }
    }

    private TimeZoneJDK(TimeZone jdkTz) {
        fJdkTz = (TimeZone)jdkTz.clone();
    }
    
    public static com.ibm.icu.util.TimeZone wrap(TimeZone jdkTz) {
        if (jdkTz instanceof TimeZoneICU) {
            return ((TimeZoneICU)jdkTz).unwrap();
        }
        return new TimeZoneJDK(jdkTz);
    }
    
    public TimeZone unwrap() {
        return (TimeZone)fJdkTz.clone();
    }

    @Override
    public Object clone() {
        if (isFrozen()) {
            return this;
        }
        return cloneAsThawed();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof TimeZoneJDK) {
            return (((TimeZoneJDK)obj).fJdkTz).equals(fJdkTz);
        }
        return false;
    }

    //public String getDisplayName()
    //public String getDisplayName(boolean daylight, int style)
    //public String getDisplayName(Locale locale)
    //public String getDisplayName(ULocale locale)
    @Override
    public String getDisplayName(boolean daylight, int style, Locale locale) {
        return fJdkTz.getDisplayName(daylight, style, locale);
    }
    
    @Override
    public String getDisplayName(boolean daylight, int style, ULocale locale) {
        return fJdkTz.getDisplayName(daylight, style, locale.toLocale());
    }

    @Override
    public int getDSTSavings() {
        return fJdkTz.getDSTSavings();
    }

    @Override
    public String getID() {
        return fJdkTz.getID();
    }

    @Override
    public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
        return fJdkTz.getOffset(era, year, month, day, dayOfWeek, milliseconds);
    }

    @Override
    public int getOffset(long date) {
        return fJdkTz.getOffset(date);
    }

    @Override
    public void getOffset(long date, boolean local, int[] offsets) {
        synchronized(this) {
            if (fJdkCal == null) {
                fJdkCal = new GregorianCalendar(fJdkTz);
            }
            if (local) {
                int fields[] = new int[6];
                Grego.timeToFields(date, fields);
                int hour, min, sec, mil;
                int tmp = fields[5];
                mil = tmp % 1000;
                tmp /= 1000;
                sec = tmp % 60;
                tmp /= 60;
                min = tmp % 60;
                hour = tmp / 60;
                fJdkCal.clear();
                fJdkCal.set(fields[0], fields[1], fields[2], hour, min, sec);
                fJdkCal.set(java.util.Calendar.MILLISECOND, mil);

                int doy1, hour1, min1, sec1, mil1;
                doy1 = fJdkCal.get(java.util.Calendar.DAY_OF_YEAR);
                hour1 = fJdkCal.get(java.util.Calendar.HOUR_OF_DAY);
                min1 = fJdkCal.get(java.util.Calendar.MINUTE);
                sec1 = fJdkCal.get(java.util.Calendar.SECOND);
                mil1 = fJdkCal.get(java.util.Calendar.MILLISECOND);

                if (fields[4] != doy1 || hour != hour1 || min != min1 || sec != sec1 || mil != mil1) {
                    // Calendar field(s) were changed due to the adjustment for non-existing time
                    // Note: This code does not support non-existing local time at year boundary properly.
                    // But, it should work fine for real timezones.
                    int dayDelta = Math.abs(doy1 - fields[4]) > 1 ? 1 : doy1 - fields[4];
                    int delta = ((((dayDelta * 24) + hour1 - hour) * 60 + min1 - min) * 60 + sec1 - sec) * 1000 + mil1 - mil;

                    // In this case, we use the offsets before the transition
                    fJdkCal.setTimeInMillis(fJdkCal.getTimeInMillis() - delta - 1);
                }
            } else {
                fJdkCal.setTimeInMillis(date);
            }
            offsets[0] = fJdkCal.get(java.util.Calendar.ZONE_OFFSET);
            offsets[1] = fJdkCal.get(java.util.Calendar.DST_OFFSET);
        }
    }

    @Override
    public int getRawOffset() {
        return fJdkTz.getRawOffset();
    }

    @Override
    public int hashCode() {
        return fJdkTz.hashCode();
    }

    @Override
    public boolean hasSameRules(com.ibm.icu.util.TimeZone other) {
        return other.hasSameRules(TimeZoneJDK.wrap(fJdkTz));
    }

    @Override
    public boolean inDaylightTime(Date date) {
        return fJdkTz.inDaylightTime(date);
    }

    @Override
    public void setID(String ID) {
        if (isFrozen()) {
            throw new UnsupportedOperationException("Attempt to modify a frozen TimeZoneJDK instance.");
        }
        fJdkTz.setID(ID);
    }

    @Override
    public void setRawOffset(int offsetMillis) {
        if (isFrozen()) {
            throw new UnsupportedOperationException("Attempt to modify a frozen TimeZoneJDK instance.");
        }
        fJdkTz.setRawOffset(offsetMillis);
    }

    @Override
    public boolean useDaylightTime() {
        return fJdkTz.useDaylightTime();
    }

    @Override
    public boolean observesDaylightTime() {
        if (mObservesDaylightTime != null) {
            // Java 7+
            try {
                return (Boolean)mObservesDaylightTime.invoke(fJdkTz, (Object[]) null);
            } catch (IllegalAccessException e) {
            } catch (IllegalArgumentException e) {
            } catch (InvocationTargetException e) {
            }
        }
        return super.observesDaylightTime();
    }

    // Freezable stuffs
    private volatile transient boolean fIsFrozen = false;

    @Override
    public boolean isFrozen() {
        return fIsFrozen;
    }

    @Override
    public com.ibm.icu.util.TimeZone freeze() {
        fIsFrozen = true;
        return this;
    }

    @Override
    public com.ibm.icu.util.TimeZone cloneAsThawed() {
        TimeZoneJDK tz = (TimeZoneJDK)super.cloneAsThawed();
        tz.fJdkTz = (TimeZone)fJdkTz.clone();
        tz.fJdkCal = null;  // To be instantiated when necessary
        tz.fIsFrozen = false;
        return tz;
    }

}
