/*
 * Copyright (C) 2013 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;

import android.content.ContentValues;
import android.database.Cursor;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.HexDump;

import java.util.Arrays;
import java.util.Date;

/**
 * Tracker for an incoming SMS message ready to broadcast to listeners.
 * This is similar to {@link com.android.internal.telephony.SMSDispatcher.SmsTracker} used for
 * outgoing messages.
 */
public class InboundSmsTracker {

    // Fields for single and multi-part messages
    private final byte[] mPdu;
    private final long mTimestamp;
    private final int mDestPort;
    private final boolean mIs3gpp2;
    private final boolean mIs3gpp2WapPdu;
    private final String mMessageBody;

    // Fields for concatenating multi-part SMS messages
    private final String mAddress;
    private final int mReferenceNumber;
    private final int mSequenceNumber;
    private final int mMessageCount;

    // Fields for deleting this message after delivery
    private String mDeleteWhere;
    private String[] mDeleteWhereArgs;

    /**
     * Copied from SmsMessageBase#getDisplayOriginatingAddress used for blocking messages.
     * DisplayAddress could be email address if this message was from an email gateway, otherwise
     * same as mAddress. Email gateway might set a generic gateway address as the mAddress which
     * could not be used for blocking check and append the display email address at the beginning
     * of the message body. In that case, display email address is only available for the first SMS
     * in the Multi-part SMS.
     */
    private final String mDisplayAddress;

    @VisibleForTesting
    /** Destination port flag bit for no destination port. */
    public static final int DEST_PORT_FLAG_NO_PORT = (1 << 16);

    /** Destination port flag bit to indicate 3GPP format message. */
    private static final int DEST_PORT_FLAG_3GPP = (1 << 17);

    @VisibleForTesting
    /** Destination port flag bit to indicate 3GPP2 format message. */
    public static final int DEST_PORT_FLAG_3GPP2 = (1 << 18);

    @VisibleForTesting
    /** Destination port flag bit to indicate 3GPP2 format WAP message. */
    public static final int DEST_PORT_FLAG_3GPP2_WAP_PDU = (1 << 19);

    /** Destination port mask (16-bit unsigned value on GSM and CDMA). */
    private static final int DEST_PORT_MASK = 0xffff;

    @VisibleForTesting
    public static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND "
            + "count=? AND (destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU
            + "=0) AND deleted=0";

    @VisibleForTesting
    public static final String SELECT_BY_REFERENCE_3GPP2WAP = "address=? AND reference_number=? "
            + "AND count=? AND (destination_port & "
            + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=" + DEST_PORT_FLAG_3GPP2_WAP_PDU + ") AND deleted=0";

    /**
     * Create a tracker for a single-part SMS.
     *
     * @param pdu the message PDU
     * @param timestamp the message timestamp
     * @param destPort the destination port
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     * @param address originating address
     * @param displayAddress email address if this message was from an email gateway, otherwise same
     *                       as originating address
     */
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
            boolean is3gpp2WapPdu, String address, String displayAddress, String messageBody) {
        mPdu = pdu;
        mTimestamp = timestamp;
        mDestPort = destPort;
        mIs3gpp2 = is3gpp2;
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mMessageBody = messageBody;
        mAddress = address;
        mDisplayAddress = displayAddress;
        // fields for multi-part SMS
        mReferenceNumber = -1;
        mSequenceNumber = getIndexOffset();     // 0 or 1, depending on type
        mMessageCount = 1;
    }

    /**
     * Create a tracker for a multi-part SMS. Sequence numbers start at 1 for 3GPP and regular
     * concatenated 3GPP2 messages, but CDMA WAP push sequence numbers start at 0. The caller will
     * subtract 1 if necessary so that the sequence number is always 0-based. When loading and
     * saving to the raw table, the sequence number is adjusted if necessary for backwards
     * compatibility.
     *
     * @param pdu the message PDU
     * @param timestamp the message timestamp
     * @param destPort the destination port
     * @param is3gpp2 true for 3GPP2 format; false for 3GPP format
     * @param address originating address, or email if this message was from an email gateway
     * @param displayAddress email address if this message was from an email gateway, otherwise same
     *                       as originating address
     * @param referenceNumber the concatenated reference number
     * @param sequenceNumber the sequence number of this segment (0-based)
     * @param messageCount the total number of segments
     * @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
     */
    public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
            String address, String displayAddress, int referenceNumber, int sequenceNumber,
            int messageCount, boolean is3gpp2WapPdu, String messageBody) {
        mPdu = pdu;
        mTimestamp = timestamp;
        mDestPort = destPort;
        mIs3gpp2 = is3gpp2;
        mIs3gpp2WapPdu = is3gpp2WapPdu;
        mMessageBody = messageBody;
        // fields used for check blocking message
        mDisplayAddress = displayAddress;
        // fields for multi-part SMS
        mAddress = address;
        mReferenceNumber = referenceNumber;
        mSequenceNumber = sequenceNumber;
        mMessageCount = messageCount;
    }

    /**
     * Create a new tracker from the row of the raw table pointed to by Cursor.
     * Since this constructor is used only for recovery during startup, the Dispatcher is null.
     * @param cursor a Cursor pointing to the row to construct this SmsTracker for
     */
    public InboundSmsTracker(Cursor cursor, boolean isCurrentFormat3gpp2) {
        mPdu = HexDump.hexStringToByteArray(cursor.getString(InboundSmsHandler.PDU_COLUMN));

        if (cursor.isNull(InboundSmsHandler.DESTINATION_PORT_COLUMN)) {
            mDestPort = -1;
            mIs3gpp2 = isCurrentFormat3gpp2;
            mIs3gpp2WapPdu = false;
        } else {
            int destPort = cursor.getInt(InboundSmsHandler.DESTINATION_PORT_COLUMN);
            if ((destPort & DEST_PORT_FLAG_3GPP) != 0) {
                mIs3gpp2 = false;
            } else if ((destPort & DEST_PORT_FLAG_3GPP2) != 0) {
                mIs3gpp2 = true;
            } else {
                mIs3gpp2 = isCurrentFormat3gpp2;
            }
            mIs3gpp2WapPdu = ((destPort & DEST_PORT_FLAG_3GPP2_WAP_PDU) != 0);
            mDestPort = getRealDestPort(destPort);
        }

        mTimestamp = cursor.getLong(InboundSmsHandler.DATE_COLUMN);
        mAddress = cursor.getString(InboundSmsHandler.ADDRESS_COLUMN);
        mDisplayAddress = cursor.getString(InboundSmsHandler.DISPLAY_ADDRESS_COLUMN);

        if (cursor.getInt(InboundSmsHandler.COUNT_COLUMN) == 1) {
            // single-part message
            long rowId = cursor.getLong(InboundSmsHandler.ID_COLUMN);
            mReferenceNumber = -1;
            mSequenceNumber = getIndexOffset();     // 0 or 1, depending on type
            mMessageCount = 1;
            mDeleteWhere = InboundSmsHandler.SELECT_BY_ID;
            mDeleteWhereArgs = new String[]{Long.toString(rowId)};
        } else {
            // multi-part message
            mReferenceNumber = cursor.getInt(InboundSmsHandler.REFERENCE_NUMBER_COLUMN);
            mMessageCount = cursor.getInt(InboundSmsHandler.COUNT_COLUMN);

            // GSM sequence numbers start at 1; CDMA WDP datagram sequence numbers start at 0
            mSequenceNumber = cursor.getInt(InboundSmsHandler.SEQUENCE_COLUMN);
            int index = mSequenceNumber - getIndexOffset();

            if (index < 0 || index >= mMessageCount) {
                throw new IllegalArgumentException("invalid PDU sequence " + mSequenceNumber
                        + " of " + mMessageCount);
            }

            mDeleteWhere = getQueryForSegments();
            mDeleteWhereArgs = new String[]{mAddress,
                    Integer.toString(mReferenceNumber), Integer.toString(mMessageCount)};
        }
        mMessageBody = cursor.getString(InboundSmsHandler.MESSAGE_BODY_COLUMN);
    }

    public ContentValues getContentValues() {
        ContentValues values = new ContentValues();
        values.put("pdu", HexDump.toHexString(mPdu));
        values.put("date", mTimestamp);
        // Always set the destination port, since it now contains message format flags.
        // Port is a 16-bit value, or -1, so clear the upper bits before setting flags.
        int destPort;
        if (mDestPort == -1) {
            destPort = DEST_PORT_FLAG_NO_PORT;
        } else {
            destPort = mDestPort & DEST_PORT_MASK;
        }
        if (mIs3gpp2) {
            destPort |= DEST_PORT_FLAG_3GPP2;
        } else {
            destPort |= DEST_PORT_FLAG_3GPP;
        }
        if (mIs3gpp2WapPdu) {
            destPort |= DEST_PORT_FLAG_3GPP2_WAP_PDU;
        }
        values.put("destination_port", destPort);
        if (mAddress != null) {
            values.put("address", mAddress);
            values.put("display_originating_addr", mDisplayAddress);
            values.put("reference_number", mReferenceNumber);
            values.put("sequence", mSequenceNumber);
        }
        values.put("count", mMessageCount);
        values.put("message_body", mMessageBody);
        return values;
    }

    /**
     * Get the port number, or -1 if there is no destination port.
     * @param destPort the destination port value, with flags
     * @return the real destination port, or -1 for no port
     */
    public static int getRealDestPort(int destPort) {
        if ((destPort & DEST_PORT_FLAG_NO_PORT) != 0) {
            return -1;
        } else {
           return destPort & DEST_PORT_MASK;
        }
    }

    /**
     * Update the values to delete all rows of the message from raw table.
     * @param deleteWhere the selection to use
     * @param deleteWhereArgs the selection args to use
     */
    public void setDeleteWhere(String deleteWhere, String[] deleteWhereArgs) {
        mDeleteWhere = deleteWhere;
        mDeleteWhereArgs = deleteWhereArgs;
    }

    public String toString() {
        StringBuilder builder = new StringBuilder("SmsTracker{timestamp=");
        builder.append(new Date(mTimestamp));
        builder.append(" destPort=").append(mDestPort);
        builder.append(" is3gpp2=").append(mIs3gpp2);
        if (InboundSmsHandler.VDBG) {
            builder.append(" address=").append(mAddress);
            builder.append(" timestamp=").append(mTimestamp);
            builder.append(" messageBody=").append(mMessageBody);
        }
        builder.append(" display_originating_addr=").append(mDisplayAddress);
        builder.append(" refNumber=").append(mReferenceNumber);
        builder.append(" seqNumber=").append(mSequenceNumber);
        builder.append(" msgCount=").append(mMessageCount);
        if (mDeleteWhere != null) {
            builder.append(" deleteWhere(").append(mDeleteWhere);
            builder.append(") deleteArgs=(").append(Arrays.toString(mDeleteWhereArgs));
            builder.append(')');
        }
        builder.append('}');
        return builder.toString();
    }

    public byte[] getPdu() {
        return mPdu;
    }

    public long getTimestamp() {
        return mTimestamp;
    }

    public int getDestPort() {
        return mDestPort;
    }

    public boolean is3gpp2() {
        return mIs3gpp2;
    }

    public String getFormat() {
        return mIs3gpp2 ? SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
    }

    public String getQueryForSegments() {
        return mIs3gpp2WapPdu ? SELECT_BY_REFERENCE_3GPP2WAP : SELECT_BY_REFERENCE;
    }

    /**
     * Get the query to find the exact same message/message segment in the db.
     * @return Pair with where as Pair.first and whereArgs as Pair.second
     */
    public Pair<String, String[]> getExactMatchDupDetectQuery() {
        // convert to strings for query
        String address = getAddress();
        String refNumber = Integer.toString(getReferenceNumber());
        String count = Integer.toString(getMessageCount());
        String seqNumber = Integer.toString(getSequenceNumber());
        String date = Long.toString(getTimestamp());
        String messageBody = getMessageBody();

        String where = "address=? AND reference_number=? AND count=? AND sequence=? AND "
                + "date=? AND message_body=?";
        where = addDestPortQuery(where);
        String[] whereArgs = new String[]{address, refNumber, count, seqNumber, date, messageBody};

        return new Pair<>(where, whereArgs);
    }

    /**
     * The key differences here compared to exact match are:
     * - this is applicable only for multi-part message segments
     * - this does not match date or message_body
     * - this matches deleted=0 (undeleted segments)
     * The only difference as compared to getQueryForSegments() is that this checks for sequence as
     * well.
     * @return Pair with where as Pair.first and whereArgs as Pair.second
     */
    public Pair<String, String[]> getInexactMatchDupDetectQuery() {
        if (getMessageCount() == 1) return null;

        // convert to strings for query
        String address = getAddress();
        String refNumber = Integer.toString(getReferenceNumber());
        String count = Integer.toString(getMessageCount());
        String seqNumber = Integer.toString(getSequenceNumber());

        String where = "address=? AND reference_number=? AND count=? AND sequence=? AND "
                + "deleted=0";
        where = addDestPortQuery(where);
        String[] whereArgs = new String[]{address, refNumber, count, seqNumber};

        return new Pair<>(where, whereArgs);
    }

    private String addDestPortQuery(String where) {
        String whereDestPort;
        if (mIs3gpp2WapPdu) {
            whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "="
                + DEST_PORT_FLAG_3GPP2_WAP_PDU;
        } else {
            whereDestPort = "destination_port & " + DEST_PORT_FLAG_3GPP2_WAP_PDU + "=0";
        }
        return where + " AND (" + whereDestPort + ")";
    }

    /**
     * Sequence numbers for concatenated messages start at 1. The exception is CDMA WAP PDU
     * messages, which use a 0-based index.
     * @return the offset to use to convert between mIndex and the sequence number
     */
    public int getIndexOffset() {
        return (mIs3gpp2 && mIs3gpp2WapPdu) ? 0 : 1;
    }

    public String getAddress() {
        return mAddress;
    }

    public String getDisplayAddress() {
        return mDisplayAddress;
    }

    public String getMessageBody() {
        return mMessageBody;
    }

    public int getReferenceNumber() {
        return mReferenceNumber;
    }

    public int getSequenceNumber() {
        return mSequenceNumber;
    }

    public int getMessageCount() {
        return mMessageCount;
    }

    public String getDeleteWhere() {
        return mDeleteWhere;
    }

    public String[] getDeleteWhereArgs() {
        return mDeleteWhereArgs;
    }
}
