/*
    Реализация спецификаций 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.microedition.system.protocol.obex;

import java.io.*;
import java.util.*;
import javax.obex.*;

public abstract class CustomHeaderSet extends Object implements HeaderSet
{
    private static final byte[] HEADER_IDS;

    static {
        HEADER_IDS = new byte[] {
            (byte) 0x01, (byte) 0x05, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35,
            (byte) 0x36, (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x3b, (byte) 0x3c, (byte) 0x3d,
            (byte) 0x3e, (byte) 0x3f, (byte) 0x42, (byte) 0x44, (byte) 0x46, (byte) 0x47, (byte) 0x4a, (byte) 0x4c,
            (byte) 0x4f, (byte) 0x70, (byte) 0x71, (byte) 0x72, (byte) 0x73, (byte) 0x74, (byte) 0x75, (byte) 0x76,
            (byte) 0x77, (byte) 0x78, (byte) 0x79, (byte) 0x7a, (byte) 0x7b, (byte) 0x7c, (byte) 0x7d, (byte) 0x7e,
            (byte) 0x7f, (byte) 0xb0, (byte) 0xb1, (byte) 0xb2, (byte) 0xb3, (byte) 0xb4, (byte) 0xb5, (byte) 0xb6,
            (byte) 0xb7, (byte) 0xb8, (byte) 0xb9, (byte) 0xba, (byte) 0xbb, (byte) 0xbc, (byte) 0xbd, (byte) 0xbe,
            (byte) 0xbf, (byte) 0xc0, (byte) 0xc3, (byte) 0xc4, (byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3,
            (byte) 0xf4, (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xfb,
            (byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff
        };
        /* 01-42 - String
         * 44-44 - Calendar
         * c4-c4 - Calendar
         * 46-7f - byte[]
         * b0-bf - Byte
         * c0-c3 - Long
         * f0-ff - Long
         */
    }

    private static int indexOf(int headerID) {
        return headerID < 0x00 || headerID > 0xff ? -1 : Array.findb(HEADER_IDS, HEADER_IDS.length - 1, headerID);
    }

    private final Object[] values;

    protected CustomHeaderSet() {
        this.values = new Object[HEADER_IDS.length];
    }

    public abstract int getResponseCode() throws IOException;

    public void createAuthenticationChallenge(String realm, boolean userID, boolean access) {
    }

    public void setHeader(int headerID, Object headerValue) {
        int index;
        if((index = indexOf(headerID)) < 0)
        {
            throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerID имеет недопустимое значение.");
        }
        if(headerValue != null)
        {
            if(headerID >= 0x01 && headerID <= 0x42)
            {
                if(!(headerValue instanceof String))
                {
                    throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerValue имеет недопустимое значение.");
                }
            }
            else if(headerID == 0x44 || headerID == 0xc4)
            {
                if(!(headerValue instanceof Calendar))
                {
                    throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerValue имеет недопустимое значение.");
                }
                headerValue = ((Calendar) headerValue).getTime();
            }
            else if(headerID >= 0x46 && headerID <= 0x7f)
            {
                int len;
                byte[] value;
                if(!(headerValue instanceof byte[]))
                {
                    throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerValue имеет недопустимое значение.");
                }
                Array.copy(value = (byte[]) headerValue, 0, value = new byte[len = value.length], 0, len);
                headerValue = value;
            }
            else if(headerID >= 0xb0 && headerID <= 0xbf)
            {
                if(!(headerValue instanceof Byte))
                {
                    throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerValue имеет недопустимое значение.");
                }
            }
            else
            {
                long value;
                if(!(headerValue instanceof Long) || (value = ((Long) headerValue).longValue()) < 0L || value > 0xffffffffL)
                {
                    throw new IllegalArgumentException("HeaderSet.setHeader: аргумент headerValue имеет недопустимое значение.");
                }
            }
        }
        values[index] = headerValue;
    }

    public int[] getHeaderList() throws IOException {
        int len;
        int pos = 0;
        int[] result = new int[len = HEADER_IDS.length];
        Object[] values = this.values;
        for(int i = 0; i < len; i++) if(values[i] != null) result[pos++] = HEADER_IDS[i] & 0xff;
        if(pos < len) Array.copy(result, 0, result = new int[pos], 0, pos);
        return result;
    }

    public Object getHeader(int headerID) throws IOException {
        int index;
        Object result;
        if((index = indexOf(headerID)) < 0)
        {
            throw new IllegalArgumentException("HeaderSet.getHeader: аргумент headerID имеет недопустимое значение.");
        }
        if((result = values[index]) instanceof Date)
        {
            Calendar calendar;
            (calendar = Calendar.getInstance()).setTime((Date) result);
            result = calendar;
        }
        else if(result instanceof byte[])
        {
            int len;
            byte[] value;
            Array.copy(value = (byte[]) result, 0, value = new byte[len = value.length], 0, len);
            result = value;
        }
        return result;
    }
}
