/*
 * Copyright (C) 2017 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.
 */
/*
 * Copyright (c) 2017, The Linux Foundation.
 */

/*
 * Copyright 2012 Giesecke & Devrient GmbH.
 *
 * 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.se.security.gpac;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;

/**
 * The AID-REF-DO is used for retrieving and storing the corresponding access rules for an SE
 * application (which is identified by its AID) from and to the ARA. Two different AID reference
 * data objects exist and one of these can be chosen and applied for a GET DATA and STORE DATA
 * command
 */
public class AID_REF_DO extends BerTlv {

    public static final int TAG = 0x4F;
    public static final int TAG_DEFAULT_APPLICATION = 0xC0;

    private static final byte[] CARRIER_PRIVILEGE_AID = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
    private byte[] mAid = new byte[0];

    public AID_REF_DO(byte[] rawData, int tag, int valueIndex, int valueLength) {
        super(rawData, tag, valueIndex, valueLength);
    }

    public AID_REF_DO(int tag, byte[] aid) {
        super(aid, tag, 0, (aid == null ? 0 : aid.length));
        if (aid != null) mAid = aid;
    }

    public AID_REF_DO(int tag) {
        super(null, tag, 0, 0);
    }

    /**
     * Comapares two AID_REF_DO objects and returns true if they are equal
     */
    public static boolean equals(AID_REF_DO obj1, AID_REF_DO obj2) {
        if (obj1 == null) {
            return (obj2 == null) ? true : false;
        }
        return obj1.equals(obj2);
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        b.append("AID_REF_DO: ");
        try {
            this.build(out);
            b.append(BerTlv.toHex(out.toByteArray()));
        } catch (Exception e) {
            b.append(e.getLocalizedMessage());
        }
        return b.toString();
    }

    public byte[] getAid() {
        return mAid;
    }

    /**
     * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 -
     * 16
     * bytes
     *
     * <p>Value: AID: identifies a specific application Empty: refers to all SE applications
     *
     * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field
     */
    @Override
    public void interpret() throws ParserException {
        byte[] data = getRawData();
        int index = getValueIndex();

        if (getTag() == TAG_DEFAULT_APPLICATION) {
            if (getValueLength() != 0) {
                throw new ParserException("Invalid value length for AID-REF-DO!");
            }
        } else if (getTag() == TAG) {

            // quick checks
            if ((getValueLength() < 5 || getValueLength() > 16) && getValueLength() != 0) {
                throw new ParserException("Invalid value length for AID-REF-DO!");
            }

            if (index + getValueLength() > data.length) {
                throw new ParserException("Not enough data for AID-REF-DO!");
            }

            mAid = new byte[getValueLength()];
            System.arraycopy(data, index, mAid, 0, getValueLength());

        } else {
            throw new ParserException("Invalid Tag for AID-REF-DO!");
        }
    }

    /**
     * Tags: C0 -> Length: 0 -> Default selected application (all channels) 4F -> Length: 0 or 5 -
     * 16
     * bytes
     *
     * <p>Value: AID: identifies a specific application Empty: refers to all SE applications
     *
     * <p>Length: 5-16 for an AID according to ISO/IEC7816-5 0 for empty value field
     */
    @Override
    public void build(ByteArrayOutputStream stream) throws DO_Exception {

        if (getTag() == TAG_DEFAULT_APPLICATION) {
            if (mAid.length > 0) {
                throw new DO_Exception("No value allowed for default selected application!");
            }
            stream.write(getTag());
            stream.write(0x00);
        } else if (getTag() == TAG) {

            // quick check
            if (getValueLength() != 0) {
                if (getValueLength() < 5 || getValueLength() > 16) {
                    throw new DO_Exception("Invalid length of AID!");
                }
            }

            stream.write(getTag());
            stream.write(mAid.length);
            try {
                stream.write(mAid);
            } catch (IOException ioe) {
                throw new DO_Exception("AID could not be written!");
            }
        } else {
            throw new DO_Exception("AID-REF-DO must either be C0 or 4F!");
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof AID_REF_DO) {
            AID_REF_DO aid_ref_do = (AID_REF_DO) obj;
            if (getTag() == aid_ref_do.getTag()) {
                return Arrays.equals(mAid, aid_ref_do.mAid);
            }
        }
        return false;
    }

    /** Checks if the AID_REF_DO is a Carrier Privilege rule */
    public boolean isCarrierPrivilege() {
        return Arrays.equals(mAid, CARRIER_PRIVILEGE_AID);
    }

    /** Creates a Carrier Privilege AID_REF_DO */
    public static AID_REF_DO createCarrierPrivilegeAid() {
        return new AID_REF_DO(AID_REF_DO.TAG, CARRIER_PRIVILEGE_AID);
    }
}
