/*
 * Copyright (C) 2018 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.internal.telephony.uicc.euicc;

import android.telephony.Rlog;

import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
import com.android.internal.telephony.uicc.asn1.Asn1Node;
import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
import com.android.internal.telephony.uicc.asn1.TagNotFoundException;

import java.util.Arrays;

/**
 * This represents the version of GSMA SGP.22 spec in the form of 3 numbers: major, minor, and
 * revision.
 */
public final class EuiccSpecVersion implements Comparable<EuiccSpecVersion> {
    private static final String LOG_TAG = "EuiccSpecVer";

    // ASN.1 Tags
    private static final int TAG_ISD_R_APP_TEMPLATE = 0xE0;
    private static final int TAG_VERSION = 0x82;

    private final int[] mVersionValues = new int[3];

    /**
     * Parses the response of opening a logical channel to get spec version of the eUICC card.
     *
     * @return Parsed spec version. If any error is encountered, null will be returned.
     */
    public static EuiccSpecVersion fromOpenChannelResponse(byte[] response) {
        Asn1Node node;
        try {
            Asn1Decoder decoder = new Asn1Decoder(response);
            if (!decoder.hasNextNode()) {
                return null;
            }
            node = decoder.nextNode();
        } catch (InvalidAsn1DataException e) {
            Rlog.e(LOG_TAG, "Cannot parse the select response of ISD-R.", e);
            return null;
        }
        try {
            byte[] versionType;
            if (node.getTag() == TAG_ISD_R_APP_TEMPLATE) {
                versionType = node.getChild(TAG_VERSION).asBytes();
            } else {
                versionType =
                        node.getChild(TAG_ISD_R_APP_TEMPLATE, TAG_VERSION).asBytes();
            }
            if (versionType.length == 3) {
                return new EuiccSpecVersion(versionType);
            } else {
                Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex());
            }
        } catch (InvalidAsn1DataException | TagNotFoundException e) {
            Rlog.e(LOG_TAG, "Cannot parse select response of ISD-R: " + node.toHex());
        }
        return null;
    }

    public EuiccSpecVersion(int major, int minor, int revision) {
        mVersionValues[0] = major;
        mVersionValues[1] = minor;
        mVersionValues[2] = revision;
    }

    /**
     * @param version The version bytes from ASN1 data. The length must be 3.
     */
    public EuiccSpecVersion(byte[] version) {
        mVersionValues[0] = version[0] & 0xFF;
        mVersionValues[1] = version[1] & 0xFF;
        mVersionValues[2] = version[2] & 0xFF;
    }

    public int getMajor() {
        return mVersionValues[0];
    }

    public int getMinor() {
        return mVersionValues[1];
    }

    public int getRevision() {
        return mVersionValues[2];
    }

    @Override
    public int compareTo(EuiccSpecVersion that) {
        if (getMajor() > that.getMajor()) {
            return 1;
        } else if (getMajor() < that.getMajor()) {
            return -1;
        }
        if (getMinor() > that.getMinor()) {
            return 1;
        } else if (getMinor() < that.getMinor()) {
            return -1;
        }
        if (getRevision() > that.getRevision()) {
            return 1;
        } else if (getRevision() < that.getRevision()) {
            return -1;
        }
        return 0;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        return Arrays.equals(mVersionValues, ((EuiccSpecVersion) obj).mVersionValues);
    }

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

    @Override
    public String toString() {
        return mVersionValues[0] + "." + mVersionValues[1] + "." + mVersionValues[2];
    }
}
