/*
    Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
    и других спецификаций для функционирования компактных приложений на языке
    Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

    Copyright © 2016–2017, 2019–2022 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package malik.emulator.time;

import java.util.*;
import malik.emulator.util.*;

public class BasicTimeZoneCollection extends Object implements TimeZoneCollection
{
    private int count;
    private BasicTimeZone[] zones;
    private BasicTimeZone defaultZone;
    private final BasicTimeZone utc;
    private final Object monitor;

    public BasicTimeZoneCollection() {
        this((int) MalikSystem.syscall(1L, 0x000c));
    }

    public BasicTimeZoneCollection(int defaultOffsetInMillis) {
        int count;
        BasicTimeZone[] zones;
        BasicTimeZone defaultZone;
        BasicTimeZone utc = new BasicTimeZone("GMT", getAllIDs(0), "Время в формате UTC", 0);
        if(defaultOffsetInMillis != 0)
        {
            count = 2;
            defaultZone = new BasicTimeZone(
                (new StringBuilder()).append("UTC").append(BasicTimeZone.offsetToString(defaultOffsetInMillis)).toString(), getAllIDs(defaultOffsetInMillis), "Местное время", defaultOffsetInMillis
            );
            zones = new BasicTimeZone[] { utc, defaultZone, null };
        } else
        {
            count = 1;
            defaultZone = utc;
            zones = new BasicTimeZone[] { utc };
        }
        this.count = count;
        this.zones = zones;
        this.defaultZone = defaultZone;
        this.utc = utc;
        this.monitor = new Object();
    }

    public String[] getAvailableIDs() {
        String[] result;
        BasicTimeZone[] zones = this.zones;
        Vector collection = new Vector();
        for(int len = count, i = 0; i < len; i++)
        {
            BasicTimeZone zone;
            for(int idslen = (zone = zones[i]).getIDsCount(), j = 0; j < idslen; j++) collection.addElement(zone.getID(j));
        }
        collection.copyInto(result = new String[collection.size()]);
        return result;
    }

    public TimeZone getDefault() {
        return defaultZone;
    }

    public TimeZone getTimeZone(String id) {
        BasicTimeZone[] zones = this.zones;
        for(int len = count, i = 0; i < len; i++)
        {
            BasicTimeZone zone;
            if((zone = zones[i]).isID(id)) return zone;
        }
        return utc;
    }

    public void add(BasicTimeZone zone) {
        if(zone == null)
        {
            throw new NullPointerException("BasicTimeZoneCollection.add: аргумент zone равен нулевой ссылке.");
        }
        synchronized(monitor)
        {
            int len;
            BasicTimeZone[] zones;
            if((len = count) == (zones = this.zones).length) Array.copy(zones, 0, zones = this.zones = new BasicTimeZone[(len << 1) + 1], 0, len);
            zones[len++] = zone;
            count = len;
        }
    }

    public void setDefault(BasicTimeZone zone) {
        if(zone == null)
        {
            throw new NullPointerException("BasicTimeZoneCollection.setDefault: аргумент zone равен нулевой ссылке.");
        }
        defaultZone = zone;
    }

    protected String[] getAllIDs(int offsetInMillis) {
        boolean negative;
        int ofs;
        int hrs;
        int min = (hrs = (negative = (ofs = offsetInMillis / 60000) < 0) ? -ofs : ofs) % 60;
        return (hrs /= 60) < 10 ? min <= 0 ? new String[] {
            hrs <= 0 ? "UTC" : null,
            new String(new char[] { 'U', 'T', 'C', negative ? '-' : '+', (char) (hrs + '0') }),
            new String(new char[] { 'U', 'T', 'C', negative ? '-' : '+', '0', (char) (hrs + '0') }),
            new String(new char[] { 'U', 'T', 'C', negative ? '-' : '+', (char) (hrs + '0'), ':', '0', '0' })
        } : new String[] {
            new String(new char[] { 'U', 'T', 'C', negative ? '-' : '+', (char) (hrs + '0'), ':', (char) (min / 10 + '0'), (char) (min % 10 + '0') })
        } : min <= 0 ? new String[] {
            new String(new char[] { 'U', 'T', 'C', negative ? '-' : '+', (char) ((hrs / 10) % 10 + '0'), (char) (hrs % 10 + '0') })
        } : null;
    }
}
