/*
 * Copyright (C) 2012 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.cellbroadcastservice;

import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE;
import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI;
import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_OTHER_EMERGENCY;
import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE;
import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI;

import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
import android.telephony.CbGeoUtils.Geometry;
import android.telephony.CbGeoUtils.LatLng;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.util.Log;
import android.util.Pair;

import com.android.cellbroadcastservice.CbGeoUtils.Circle;
import com.android.cellbroadcastservice.CbGeoUtils.Polygon;
import com.android.cellbroadcastservice.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity;
import com.android.cellbroadcastservice.SmsCbHeader.DataCodingScheme;
import com.android.internal.annotations.VisibleForTesting;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is
 * public because {@link #createSmsCbMessage(SmsCbLocation, byte[][])} is used by some test cases.
 */
public class GsmSmsCbMessage {
    private static final String TAG = GsmSmsCbMessage.class.getSimpleName();

    private static final char CARRIAGE_RETURN = 0x0d;

    private static final int PDU_BODY_PAGE_LENGTH = 82;

    /** Utility class with only static methods. */
    private GsmSmsCbMessage() { }

    /**
     * Get built-in ETWS primary messages by category. ETWS primary message does not contain text,
     * so we have to show the pre-built messages to the user.
     *
     * @param context Device context
     * @param category ETWS message category defined in SmsCbConstants
     * @return ETWS text message in string. Return an empty string if no match.
     */
    @VisibleForTesting
    public static String getEtwsPrimaryMessage(Context context, int category) {
        final Resources r = context.getResources();
        switch (category) {
            case ETWS_WARNING_TYPE_EARTHQUAKE:
                return r.getString(R.string.etws_primary_default_message_earthquake);
            case ETWS_WARNING_TYPE_TSUNAMI:
                return r.getString(R.string.etws_primary_default_message_tsunami);
            case ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI:
                return r.getString(R.string.etws_primary_default_message_earthquake_and_tsunami);
            case ETWS_WARNING_TYPE_TEST_MESSAGE:
                return r.getString(R.string.etws_primary_default_message_test);
            case ETWS_WARNING_TYPE_OTHER_EMERGENCY:
                return r.getString(R.string.etws_primary_default_message_others);
            default:
                return "";
        }
    }

    /**
     * Create a new SmsCbMessage object from a header object plus one or more received PDUs.
     *
     * @param pdus PDU bytes
     */
    public static SmsCbMessage createSmsCbMessage(Context context, SmsCbHeader header,
            SmsCbLocation location, byte[][] pdus, int slotIndex)
            throws IllegalArgumentException {
        SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
        int[] subIds = sm.getSubscriptionIds(slotIndex);
        if (subIds != null && subIds.length > 0) {
            subId = subIds[0];
        }

        long receivedTimeMillis = System.currentTimeMillis();
        if (header.isEtwsPrimaryNotification()) {
            // ETSI TS 23.041 ETWS Primary Notification message
            // ETWS primary message only contains 4 fields including serial number,
            // message identifier, warning type, and warning security information.
            // There is no field for the content/text so we get the text from the resources.
            return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(),
                    header.getSerialNumber(), location, header.getServiceCategory(), null, 0,
                    getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()),
                    SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(),
                    header.getCmasInfo(), 0, null, receivedTimeMillis, slotIndex, subId);
        } else if (header.isUmtsFormat()) {
            // UMTS format has only 1 PDU
            byte[] pdu = pdus[0];
            Pair<String, String> cbData = parseUmtsBody(header, pdu);
            String language = cbData.first;
            String body = cbData.second;
            int priority = header.isEmergencyMessage() ? SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY
                    : SmsCbMessage.MESSAGE_PRIORITY_NORMAL;
            int nrPages = pdu[SmsCbHeader.PDU_HEADER_LENGTH];
            int wacDataOffset = SmsCbHeader.PDU_HEADER_LENGTH
                    + 1 // number of pages
                    + (PDU_BODY_PAGE_LENGTH + 1) * nrPages; // cb data

            // Has Warning Area Coordinates information
            List<Geometry> geometries = null;
            int maximumWaitingTimeSec = 255;
            if (pdu.length > wacDataOffset) {
                try {
                    Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu,
                            wacDataOffset);
                    maximumWaitingTimeSec = wac.first;
                    geometries = wac.second;
                } catch (Exception ex) {
                    // Catch the exception here, the message will be considered as having no WAC
                    // information which means the message will be broadcasted directly.
                    Log.e(TAG, "Can't parse warning area coordinates, ex = " + ex.toString());
                }
            }

            return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
                    header.getGeographicalScope(), header.getSerialNumber(), location,
                    header.getServiceCategory(), language, 0, body, priority,
                    header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries,
                    receivedTimeMillis, slotIndex, subId);
        } else {
            String language = null;
            StringBuilder sb = new StringBuilder();
            for (byte[] pdu : pdus) {
                Pair<String, String> p = parseGsmBody(header, pdu);
                language = p.first;
                sb.append(p.second);
            }
            int priority = header.isEmergencyMessage() ? SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY
                    : SmsCbMessage.MESSAGE_PRIORITY_NORMAL;

            return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
                    header.getGeographicalScope(), header.getSerialNumber(), location,
                    header.getServiceCategory(), language, 0, sb.toString(), priority,
                    header.getEtwsInfo(), header.getCmasInfo(), 0, null, receivedTimeMillis,
                    slotIndex, subId);
        }
    }

    /**
     * Parse WEA Handset Action Message(WHAM) a.k.a geo-fencing trigger message.
     *
     * WEA Handset Action Message(WHAM) is a cell broadcast service message broadcast by the network
     * to direct devices to perform a geo-fencing check on selected alerts.
     *
     * WEA Handset Action Message(WHAM) requirements from ATIS-0700041 section 4
     * 1. The Warning Message contents of a WHAM shall be in Cell Broadcast(CB) data format as
     * defined in TS 23.041.
     * 2. The Warning Message Contents of WHAM shall be limited to one CB page(max 20 referenced
     * WEA messages).
     * 3. The broadcast area for a WHAM shall be the union of the broadcast areas of the referenced
     * WEA message.
     * @param pdu cell broadcast pdu, including the header
     * @return {@link GeoFencingTriggerMessage} instance
     */
    public static GeoFencingTriggerMessage createGeoFencingTriggerMessage(byte[] pdu) {
        try {
            // Header length + 1(number of page). ATIS-0700041 define the number of page of
            // geo-fencing trigger message is 1.
            int whamOffset = SmsCbHeader.PDU_HEADER_LENGTH + 1;

            BitStreamReader bitReader = new BitStreamReader(pdu, whamOffset);
            int type = bitReader.read(4);
            int length = bitReader.read(7);
            // Skip the remained 5 bits
            bitReader.skip();

            int messageIdentifierCount = (length - 2) * 8 / 32;
            List<CellBroadcastIdentity> cbIdentifiers = new ArrayList<>();
            for (int i = 0; i < messageIdentifierCount; i++) {
                // Both messageIdentifier and serialNumber are 16 bits integers.
                // ATIS-0700041 Section 5.1.6
                int messageIdentifier = bitReader.read(16);
                int serialNumber = bitReader.read(16);
                cbIdentifiers.add(new CellBroadcastIdentity(messageIdentifier, serialNumber));
            }
            return new GeoFencingTriggerMessage(type, cbIdentifiers);
        } catch (Exception ex) {
            Log.e(TAG, "create geo-fencing trigger failed, ex = " + ex.toString());
            return null;
        }
    }

    /**
     * Parse the broadcast area and maximum wait time from the Warning Area Coordinates TLV.
     *
     * @param pdu Warning Area Coordinates TLV.
     * @param wacOffset the offset of Warning Area Coordinates TLV.
     * @return a pair with the first element is maximum wait time and the second is the broadcast
     * area. The default value of the maximum wait time is 255 which means use the device default
     * value.
     */
    private static Pair<Integer, List<Geometry>> parseWarningAreaCoordinates(
            byte[] pdu, int wacOffset) {
        // little-endian
        int wacDataLength = ((pdu[wacOffset + 1] & 0xff) << 8) | (pdu[wacOffset] & 0xff);
        int offset = wacOffset + 2;

        if (offset + wacDataLength > pdu.length) {
            throw new IllegalArgumentException("Invalid wac data, expected the length of pdu at"
                    + "least " + offset + wacDataLength + ", actual is " + pdu.length);
        }

        BitStreamReader bitReader = new BitStreamReader(pdu, offset);

        int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET;

        List<Geometry> geo = new ArrayList<>();
        int remainedBytes = wacDataLength;
        while (remainedBytes > 0) {
            int type = bitReader.read(4);
            int length = bitReader.read(10);
            remainedBytes -= length;
            // Skip the 2 remained bits
            bitReader.skip();

            switch (type) {
                case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME:
                    maximumWaitTimeSec = bitReader.read(8);
                    break;
                case CbGeoUtils.GEOMETRY_TYPE_POLYGON:
                    List<LatLng> latLngs = new ArrayList<>();
                    // Each coordinate is represented by 44 bits integer.
                    // ATIS-0700041 5.2.4 Coordinate coding
                    int n = (length - 2) * 8 / 44;
                    for (int i = 0; i < n; i++) {
                        latLngs.add(getLatLng(bitReader));
                    }
                    // Skip the padding bits
                    bitReader.skip();
                    geo.add(new Polygon(latLngs));
                    break;
                case CbGeoUtils.GEOMETRY_TYPE_CIRCLE:
                    LatLng center = getLatLng(bitReader);
                    // radius = (wacRadius / 2^6). The unit of wacRadius is km, we use meter as the
                    // distance unit during geo-fencing.
                    // ATIS-0700041 5.2.5 radius coding
                    double radius = (bitReader.read(20) * 1.0 / (1 << 6)) * 1000.0;
                    geo.add(new Circle(center, radius));
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported geoType = " + type);
            }
        }
        return new Pair(maximumWaitTimeSec, geo);
    }

    /**
     * The coordinate is (latitude, longitude), represented by a 44 bits integer.
     * The coding is defined in ATIS-0700041 5.2.4
     * @param bitReader
     * @return coordinate (latitude, longitude)
     */
    private static LatLng getLatLng(BitStreamReader bitReader) {
        // wacLatitude = floor(((latitude + 90) / 180) * 2^22)
        // wacLongitude = floor(((longitude + 180) / 360) * 2^22)
        int wacLat = bitReader.read(22);
        int wacLng = bitReader.read(22);

        // latitude = wacLatitude * 180 / 2^22 - 90
        // longitude = wacLongitude * 360 / 2^22 -180
        return new LatLng((wacLat * 180.0 / (1 << 22)) - 90, (wacLng * 360.0 / (1 << 22) - 180));
    }

    /**
     * Parse and unpack the UMTS body text according to the encoding in the data coding scheme.
     *
     * @param header the message header to use
     * @param pdu the PDU to decode
     * @return a pair of string containing the language and body of the message in order
     */
    private static Pair<String, String> parseUmtsBody(SmsCbHeader header,
            byte[] pdu) {
        // Payload may contain multiple pages
        int nrPages = pdu[SmsCbHeader.PDU_HEADER_LENGTH];
        String language = header.getDataCodingSchemeStructedData().language;

        if (pdu.length < SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1)
                * nrPages) {
            throw new IllegalArgumentException("Pdu length " + pdu.length + " does not match "
                    + nrPages + " pages");
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < nrPages; i++) {
            // Each page is 82 bytes followed by a length octet indicating
            // the number of useful octets within those 82
            int offset = SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1) * i;
            int length = pdu[offset + PDU_BODY_PAGE_LENGTH];

            if (length > PDU_BODY_PAGE_LENGTH) {
                throw new IllegalArgumentException("Page length " + length
                        + " exceeds maximum value " + PDU_BODY_PAGE_LENGTH);
            }

            Pair<String, String> p = unpackBody(pdu, offset, length,
                    header.getDataCodingSchemeStructedData());
            language = p.first;
            sb.append(p.second);
        }
        return new Pair(language, sb.toString());

    }

    /**
     * Parse and unpack the GSM body text according to the encoding in the data coding scheme.
     * @param header the message header to use
     * @param pdu the PDU to decode
     * @return a pair of string containing the language and body of the message in order
     */
    private static Pair<String, String> parseGsmBody(SmsCbHeader header,
            byte[] pdu) {
        // Payload is one single page
        int offset = SmsCbHeader.PDU_HEADER_LENGTH;
        int length = pdu.length - offset;
        return unpackBody(pdu, offset, length, header.getDataCodingSchemeStructedData());
    }

    /**
     * Unpack body text from the pdu using the given encoding, position and length within the pdu.
     *
     * @param pdu The pdu
     * @param offset Position of the first byte to unpack
     * @param length Number of bytes to unpack
     * @param dcs data coding scheme
     * @return a Pair of Strings containing the language and body of the message
     */
    private static Pair<String, String> unpackBody(byte[] pdu, int offset,
            int length, DataCodingScheme dcs) {
        String body = null;

        String language = dcs.language;
        switch (dcs.encoding) {
            case SmsMessage.ENCODING_7BIT:
                body = GsmAlphabet.gsm7BitPackedToString(pdu, offset, length * 8 / 7);

                if (dcs.hasLanguageIndicator && body != null && body.length() > 2) {
                    // Language is two GSM characters followed by a CR.
                    // The actual body text is offset by 3 characters.
                    language = body.substring(0, 2);
                    body = body.substring(3);
                }
                break;

            case SmsMessage.ENCODING_16BIT:
                if (dcs.hasLanguageIndicator && pdu.length >= offset + 2) {
                    // Language is two GSM characters.
                    // The actual body text is offset by 2 bytes.
                    language = GsmAlphabet.gsm7BitPackedToString(pdu, offset, 2);
                    offset += 2;
                    length -= 2;
                }

                try {
                    body = new String(pdu, offset, (length & 0xfffe), "utf-16");
                } catch (UnsupportedEncodingException e) {
                    // Apparently it wasn't valid UTF-16.
                    throw new IllegalArgumentException("Error decoding UTF-16 message", e);
                }
                break;

            default:
                break;
        }

        if (body != null) {
            // Remove trailing carriage return
            for (int i = body.length() - 1; i >= 0; i--) {
                if (body.charAt(i) != CARRIAGE_RETURN) {
                    body = body.substring(0, i + 1);
                    break;
                }
            }
        } else {
            body = "";
        }

        return new Pair<String, String>(language, body);
    }

    /** A class use to facilitate the processing of bits stream data. */
    private static final class BitStreamReader {
        /** The bits stream represent by a bytes array. */
        private final byte[] mData;

        /** The offset of the current byte. */
        private int mCurrentOffset;

        /**
         * The remained bits of the current byte which have not been read. The most significant
         * will be read first, so the remained bits are always the least significant bits.
         */
        private int mRemainedBit;

        /**
         * Constructor
         * @param data bit stream data represent by byte array.
         * @param offset the offset of the first byte.
         */
        BitStreamReader(byte[] data, int offset) {
            mData = data;
            mCurrentOffset = offset;
            mRemainedBit = 8;
        }

        /**
         * Read the first {@code count} bits.
         * @param count the number of bits need to read
         * @return {@code bits} represent by an 32-bits integer, therefore {@code count} must be no
         * greater than 32.
         */
        public int read(int count) throws IndexOutOfBoundsException {
            int val = 0;
            while (count > 0) {
                if (count >= mRemainedBit) {
                    val <<= mRemainedBit;
                    val |= mData[mCurrentOffset] & ((1 << mRemainedBit) - 1);
                    count -= mRemainedBit;
                    mRemainedBit = 8;
                    ++mCurrentOffset;
                } else {
                    val <<= count;
                    val |= (mData[mCurrentOffset] & ((1 << mRemainedBit) - 1))
                            >> (mRemainedBit - count);
                    mRemainedBit -= count;
                    count = 0;
                }
            }
            return val;
        }

        /**
         * Skip the current bytes if the remained bits is less than 8. This is useful when
         * processing the padding or reserved bits.
         */
        public void skip() {
            if (mRemainedBit < 8) {
                mRemainedBit = 8;
                ++mCurrentOffset;
            }
        }
    }

    /**
     * Part of a GSM SMS cell broadcast message which may trigger geo-fencing logic.
     * @hide
     */
    public static final class GeoFencingTriggerMessage {
        /**
         * Indicate the list of active alerts share their warning area coordinates which means the
         * broadcast area is the union of the broadcast areas of the active alerts in this list.
         */
        public static final int TYPE_ACTIVE_ALERT_SHARE_WAC = 2;

        public final int type;
        public final List<CellBroadcastIdentity> cbIdentifiers;

        GeoFencingTriggerMessage(int type, @NonNull List<CellBroadcastIdentity> cbIdentifiers) {
            this.type = type;
            this.cbIdentifiers = cbIdentifiers;
        }

        /**
         * Whether the trigger message indicates that the broadcast areas are shared between all
         * active alerts.
         * @return true if broadcast areas are to be shared
         */
        boolean shouldShareBroadcastArea() {
            return type == TYPE_ACTIVE_ALERT_SHARE_WAC;
        }

        /**
         * The GSM cell broadcast identity
         */
        @VisibleForTesting
        public static final class CellBroadcastIdentity {
            public final int messageIdentifier;
            public final int serialNumber;
            CellBroadcastIdentity(int messageIdentifier, int serialNumber) {
                this.messageIdentifier = messageIdentifier;
                this.serialNumber = serialNumber;
            }
        }

        @Override
        public String toString() {
            String identifiers = cbIdentifiers.stream()
                    .map(cbIdentifier ->String.format("(msgId = %d, serial = %d)",
                            cbIdentifier.messageIdentifier, cbIdentifier.serialNumber))
                    .collect(Collectors.joining(","));
            return "triggerType=" + type + " identifiers=" + identifiers;
        }
    }
}
