/*
 * 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 android.net.wifi.rtt;

import android.annotation.Nullable;
import android.location.Address;
import android.net.wifi.rtt.CivicLocationKeys.CivicLocationKeysType;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.util.SparseArray;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Objects;

/**
 * Decodes the Type Length Value (TLV) elements found in a Location Civic Record as defined by IEEE
 * P802.11-REVmc/D8.0 section 9.4.2.22.13 using the format described in IETF RFC 4776.
 *
 * <p>The TLVs each define a key, value pair for a civic address type such as apt, street, city,
 * county, and country. The class provides a general getter method to extract a value for an element
 * key, returning null if not set.
 *
 * @hide
 */
public final class CivicLocation implements Parcelable {
    // Address (class) line indexes
    private static final int ADDRESS_LINE_0_ROOM_DESK_FLOOR = 0;
    private static final int ADDRESS_LINE_1_NUMBER_ROAD_SUFFIX_APT = 1;
    private static final int ADDRESS_LINE_2_CITY = 2;
    private static final int ADDRESS_LINE_3_STATE_POSTAL_CODE = 3;
    private static final int ADDRESS_LINE_4_COUNTRY = 4;

    // Buffer management
    private static final int MIN_CIVIC_BUFFER_SIZE = 3;
    private static final int MAX_CIVIC_BUFFER_SIZE = 256;
    private static final int COUNTRY_CODE_LENGTH = 2;
    private static final int BYTE_MASK = 0xFF;
    private static final int TLV_TYPE_INDEX = 0;
    private static final int TLV_LENGTH_INDEX = 1;
    private static final int TLV_VALUE_INDEX = 2;

    private final boolean mIsValid;
    private final String mCountryCode; // Two character country code (ISO 3166 standard).
    private SparseArray<String> mCivicAddressElements =
            new SparseArray<>(MIN_CIVIC_BUFFER_SIZE);


    /**
     * Constructor
     *
     * @param civicTLVs    a byte buffer containing parameters in the form type, length, value
     * @param countryCode the two letter code defined by the ISO 3166 standard
     *
     * @hide
     */
    public CivicLocation(@Nullable byte[] civicTLVs, @Nullable String countryCode) {
        this.mCountryCode = countryCode;
        if (countryCode == null || countryCode.length() != COUNTRY_CODE_LENGTH) {
            this.mIsValid = false;
            return;
        }
        boolean isValid = false;
        if (civicTLVs != null
                && civicTLVs.length >= MIN_CIVIC_BUFFER_SIZE
                && civicTLVs.length < MAX_CIVIC_BUFFER_SIZE) {
            isValid = parseCivicTLVs(civicTLVs);
        }

        mIsValid = isValid;
    }

    private CivicLocation(Parcel in) {
        mIsValid = in.readByte() != 0;
        mCountryCode = in.readString();
        mCivicAddressElements = in.readSparseArray(this.getClass().getClassLoader());
    }

    public static final @android.annotation.NonNull Creator<CivicLocation> CREATOR = new Creator<CivicLocation>() {
        @Override
        public CivicLocation createFromParcel(Parcel in) {
            return new CivicLocation(in);
        }

        @Override
        public CivicLocation[] newArray(int size) {
            return new CivicLocation[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeByte((byte) (mIsValid ? 1 : 0));
        parcel.writeString(mCountryCode);
        parcel.writeSparseArray((android.util.SparseArray) mCivicAddressElements);
    }

    /**
     * Check TLV format and store TLV key/value pairs in this object so they can be queried by key.
     *
     * @param civicTLVs the buffer of TLV elements
     * @return a boolean indicating success of the parsing process
     */
    private boolean parseCivicTLVs(byte[] civicTLVs) {
        int bufferPtr = 0;
        int bufferLength = civicTLVs.length;

        // Iterate through the sub-elements contained in the LCI IE checking the accumulated
        // element lengths do not overflow the total buffer length
        while (bufferPtr < bufferLength) {
            int civicAddressType = civicTLVs[bufferPtr + TLV_TYPE_INDEX] & BYTE_MASK;
            int civicAddressTypeLength = civicTLVs[bufferPtr + TLV_LENGTH_INDEX];
            if (civicAddressTypeLength != 0) {
                if (bufferPtr + TLV_VALUE_INDEX + civicAddressTypeLength > bufferLength) {
                    return false;
                }
                mCivicAddressElements.put(civicAddressType,
                        new String(civicTLVs, bufferPtr + TLV_VALUE_INDEX,
                                civicAddressTypeLength, StandardCharsets.UTF_8));
            }
            bufferPtr += civicAddressTypeLength + TLV_VALUE_INDEX;
        }
        return true;
    }

    /**
     * Getter for the value of a civic Address element type.
     *
     * @param key an integer code for the element type key
     * @return the string value associated with that element type
     */
    @Nullable
    public String getCivicElementValue(@CivicLocationKeysType int key) {
        return mCivicAddressElements.get(key);
    }

    /**
     * Converts a CivicLocation object to a SparseArray.
     *
     * @return the SparseArray<string> representation of the CivicLocation
     */
    @Nullable
    public SparseArray<String> toSparseArray() {
        return mCivicAddressElements;
    }

    /**
     * Generates a comma separated string of all the defined elements.
     *
     * @return a compiled string representing all elements
     */
    @Override
    public String toString() {
        return mCivicAddressElements.toString();
    }

    /**
     * Converts Civic Location to the best effort Address Object.
     *
     * @return the {@link Address} object based on the Civic Location data
     */
    @Nullable
    public Address toAddress() {
        if (!mIsValid) {
            return null;
        }
        Address address = new Address(Locale.US);
        String room = formatAddressElement("Room: ", getCivicElementValue(CivicLocationKeys.ROOM));
        String desk =
                formatAddressElement(" Desk: ", getCivicElementValue(CivicLocationKeys.DESK));
        String floor =
                formatAddressElement(", Flr: ", getCivicElementValue(CivicLocationKeys.FLOOR));
        String houseNumber = formatAddressElement("", getCivicElementValue(CivicLocationKeys.HNO));
        String houseNumberSuffix =
                formatAddressElement("", getCivicElementValue(CivicLocationKeys.HNS));
        String road =
                formatAddressElement(" ", getCivicElementValue(
                        CivicLocationKeys.PRIMARY_ROAD_NAME));
        String roadSuffix = formatAddressElement(" ", getCivicElementValue(CivicLocationKeys.STS));
        String apt = formatAddressElement(", Apt: ", getCivicElementValue(CivicLocationKeys.APT));
        String city = formatAddressElement("", getCivicElementValue(CivicLocationKeys.CITY));
        String state = formatAddressElement("", getCivicElementValue(CivicLocationKeys.STATE));
        String postalCode =
                formatAddressElement(" ", getCivicElementValue(CivicLocationKeys.POSTAL_CODE));

        // Aggregation into common address format
        String addressLine0 =
                new StringBuilder().append(room).append(desk).append(floor).toString();
        String addressLine1 =
                new StringBuilder().append(houseNumber).append(houseNumberSuffix).append(road)
                        .append(roadSuffix).append(apt).toString();
        String addressLine2 = city;
        String addressLine3 = new StringBuilder().append(state).append(postalCode).toString();
        String addressLine4 = mCountryCode;

        // Setting Address object line fields by common convention.
        address.setAddressLine(ADDRESS_LINE_0_ROOM_DESK_FLOOR, addressLine0);
        address.setAddressLine(ADDRESS_LINE_1_NUMBER_ROAD_SUFFIX_APT, addressLine1);
        address.setAddressLine(ADDRESS_LINE_2_CITY, addressLine2);
        address.setAddressLine(ADDRESS_LINE_3_STATE_POSTAL_CODE, addressLine3);
        address.setAddressLine(ADDRESS_LINE_4_COUNTRY, addressLine4);

        // Other compatible fields between the CIVIC_ADDRESS and the Address Class.
        address.setFeatureName(getCivicElementValue(CivicLocationKeys.NAM)); // Structure name
        address.setSubThoroughfare(getCivicElementValue(CivicLocationKeys.HNO));
        address.setThoroughfare(getCivicElementValue(CivicLocationKeys.PRIMARY_ROAD_NAME));
        address.setSubLocality(getCivicElementValue(CivicLocationKeys.NEIGHBORHOOD));
        address.setSubAdminArea(getCivicElementValue(CivicLocationKeys.COUNTY));
        address.setAdminArea(getCivicElementValue(CivicLocationKeys.STATE));
        address.setPostalCode(getCivicElementValue(CivicLocationKeys.POSTAL_CODE));
        address.setCountryCode(mCountryCode); // Country
        return address;
    }

    /**
     * Prepares an address element so that it can be integrated into an address line convention.
     *
     * <p>If an address element is null, the return string will be empty e.g. "".
     *
     * @param label a string defining the type of address element
     * @param value a string defining the elements value
     * @return the formatted version of the value, with null values converted to empty strings
     */
    private String formatAddressElement(String label, String value) {
        if (value != null) {
            return label + value;
        } else {
            return "";
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof CivicLocation)) {
            return false;
        }
        CivicLocation other = (CivicLocation) obj;
        return mIsValid == other.mIsValid
                && Objects.equals(mCountryCode, other.mCountryCode)
                && isSparseArrayStringEqual(mCivicAddressElements, other.mCivicAddressElements);
    }

    @Override
    public int hashCode() {
        int[] civicAddressKeys = getSparseArrayKeys(mCivicAddressElements);
        String[] civicAddressValues = getSparseArrayValues(mCivicAddressElements);
        return Objects.hash(mIsValid, mCountryCode, civicAddressKeys, civicAddressValues);
    }

    /**
     * Tests if the Civic Location object is valid
     *
     * @return a boolean defining mIsValid
     */
    public boolean isValid() {
        return mIsValid;
    }

    /**
     * Tests if two sparse arrays are equal on a key for key basis
     *
     * @param sa1 the first sparse array
     * @param sa2 the second sparse array
     * @return the boolean result after comparing values key by key
     */
    private boolean isSparseArrayStringEqual(SparseArray<String> sa1, SparseArray<String> sa2) {
        int size = sa1.size();
        if (size != sa2.size()) {
            return false;
        }
        for (int i = 0; i < size; i++) {
            String sa1Value = sa1.valueAt(i);
            String sa2Value = sa2.valueAt(i);
            if (!sa1Value.equals(sa2Value)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Extract an array of all the keys in a SparseArray<String>
     *
     * @param sa the sparse array of Strings
     * @return an integer array of all keys in the SparseArray<String>
     */
    private int[] getSparseArrayKeys(SparseArray<String> sa) {
        int size = sa.size();
        int[] keys = new int[size];
        for (int i = 0; i < size; i++) {
            keys[i] = sa.keyAt(i);
        }
        return keys;
    }

    /**
     * Extract an array of all the String values in a SparseArray<String>
     *
     * @param sa the sparse array of Strings
     * @return a String array of all values in the SparseArray<String>
     */
    private String[] getSparseArrayValues(SparseArray<String> sa) {
        int size = sa.size();
        String[] values = new String[size];
        for (int i = 0; i < size; i++) {
            values[i] = sa.valueAt(i);
        }
        return values;
    }
}
