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

import android.content.Context;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.MifareUltralight;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcB;
import android.nfc.tech.NfcBarcode;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
import android.nfc.tech.TagTechnology;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;

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

/**
 * Represents an NFC tag that has been discovered.
 * <p>
 * {@link Tag} is an immutable object that represents the state of a NFC tag at
 * the time of discovery. It can be used as a handle to {@link TagTechnology} classes
 * to perform advanced operations, or directly queried for its ID via {@link #getId} and the
 * set of technologies it contains via {@link #getTechList}. Arrays passed to and
 * returned by this class are <em>not</em> cloned, so be careful not to modify them.
 * <p>
 * A new tag object is created every time a tag is discovered (comes into range), even
 * if it is the same physical tag. If a tag is removed and then returned into range, then
 * only the most recent tag object can be successfully used to create a {@link TagTechnology}.
 *
 * <h3>Tag Dispatch</h3>
 * When a tag is discovered, a {@link Tag} object is created and passed to a
 * single activity via the {@link NfcAdapter#EXTRA_TAG} extra in an
 * {@link android.content.Intent} via {@link Context#startActivity}. A four stage dispatch is used
 * to select the
 * most appropriate activity to handle the tag. The Android OS executes each stage in order,
 * and completes dispatch as soon as a single matching activity is found. If there are multiple
 * matching activities found at any one stage then the Android activity chooser dialog is shown
 * to allow the user to select the activity to receive the tag.
 *
 * <p>The Tag dispatch mechanism was designed to give a high probability of dispatching
 * a tag to the correct activity without showing the user an activity chooser dialog.
 * This is important for NFC interactions because they are very transient -- if a user has to
 * move the Android device to choose an application then the connection will likely be broken.
 *
 * <h4>1. Foreground activity dispatch</h4>
 * A foreground activity that has called
 * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} is
 * given priority. See the documentation on
 * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} for
 * its usage.
 * <h4>2. NDEF data dispatch</h4>
 * If the tag contains NDEF data the system inspects the first {@link NdefRecord} in the first
 * {@link NdefMessage}. If the record is a URI, SmartPoster, or MIME data
 * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_NDEF_DISCOVERED}. For URI
 * and SmartPoster records the URI is put into the intent's data field. For MIME records the MIME
 * type is put in the intent's type field. This allows activities to register to be launched only
 * when data they know how to handle is present on a tag. This is the preferred method of handling
 * data on a tag since NDEF data can be stored on many types of tags and doesn't depend on a
 * specific tag technology. 
 * See {@link NfcAdapter#ACTION_NDEF_DISCOVERED} for more detail. If the tag does not contain
 * NDEF data, or if no activity is registered
 * for {@link NfcAdapter#ACTION_NDEF_DISCOVERED} with a matching data URI or MIME type then dispatch
 * moves to stage 3.
 * <h4>3. Tag Technology dispatch</h4>
 * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_TECH_DISCOVERED} to
 * dispatch the tag to an activity that can handle the technologies present on the tag.
 * Technologies are defined as sub-classes of {@link TagTechnology}, see the package
 * {@link android.nfc.tech}. The Android OS looks for an activity that can handle one or
 * more technologies in the tag. See {@link NfcAdapter#ACTION_TECH_DISCOVERED} for more detail.
 * <h4>4. Fall-back dispatch</h4>
 * If no activity has been matched then {@link Context#startActivity} is called with
 * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. This is intended as a fall-back mechanism.
 * See {@link NfcAdapter#ACTION_TAG_DISCOVERED}.
 *
 * <h3>NFC Tag Background</h3>
 * An NFC tag is a passive NFC device, powered by the NFC field of this Android device while
 * it is in range. Tag's can come in many forms, such as stickers, cards, key fobs, or
 * even embedded in a more sophisticated device.
 * <p>
 * Tags can have a wide range of capabilities. Simple tags just offer read/write semantics,
 * and contain some one time
 * programmable areas to make read-only. More complex tags offer math operations
 * and per-sector access control and authentication. The most sophisticated tags
 * contain operating environments allowing complex interactions with the
 * code executing on the tag. Use {@link TagTechnology} classes to access a broad
 * range of capabilities available in NFC tags.
 * <p>
 */
public final class Tag implements Parcelable {
    final byte[] mId;
    final int[] mTechList;
    final String[] mTechStringList;
    final Bundle[] mTechExtras;
    final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
    final INfcTag mTagService; // interface to NFC service, will be null if mock tag

    int mConnectedTechnology;

    /**
     * Hidden constructor to be used by NFC service and internal classes.
     * @hide
     */
    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
            INfcTag tagService) {
        if (techList == null) {
            throw new IllegalArgumentException("rawTargets cannot be null");
        }
        mId = id;
        mTechList = Arrays.copyOf(techList, techList.length);
        mTechStringList = generateTechStringList(techList);
        // Ensure mTechExtras is as long as mTechList
        mTechExtras = Arrays.copyOf(techListExtras, techList.length);
        mServiceHandle = serviceHandle;
        mTagService = tagService;

        mConnectedTechnology = -1;
    }

    /**
     * Construct a mock Tag.
     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
     * <p>This constructor might be useful for mock testing.
     * @param id The tag identifier, can be null
     * @param techList must not be null
     * @return freshly constructed tag
     * @hide
     */
    public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
        // set serviceHandle to 0 and tagService to null to indicate mock tag
        return new Tag(id, techList, techListExtras, 0, null);
    }

    private String[] generateTechStringList(int[] techList) {
        final int size = techList.length;
        String[] strings = new String[size];
        for (int i = 0; i < size; i++) {
            switch (techList[i]) {
                case TagTechnology.ISO_DEP:
                    strings[i] = IsoDep.class.getName();
                    break;
                case TagTechnology.MIFARE_CLASSIC:
                    strings[i] = MifareClassic.class.getName();
                    break;
                case TagTechnology.MIFARE_ULTRALIGHT:
                    strings[i] = MifareUltralight.class.getName();
                    break;
                case TagTechnology.NDEF:
                    strings[i] = Ndef.class.getName();
                    break;
                case TagTechnology.NDEF_FORMATABLE:
                    strings[i] = NdefFormatable.class.getName();
                    break;
                case TagTechnology.NFC_A:
                    strings[i] = NfcA.class.getName();
                    break;
                case TagTechnology.NFC_B:
                    strings[i] = NfcB.class.getName();
                    break;
                case TagTechnology.NFC_F:
                    strings[i] = NfcF.class.getName();
                    break;
                case TagTechnology.NFC_V:
                    strings[i] = NfcV.class.getName();
                    break;
                case TagTechnology.NFC_BARCODE:
                    strings[i] = NfcBarcode.class.getName();
                    break;
                default:
                    throw new IllegalArgumentException("Unknown tech type " + techList[i]);
            }
        }
        return strings;
    }

    static int[] getTechCodesFromStrings(String[] techStringList) throws IllegalArgumentException {
        if (techStringList == null) {
            throw new IllegalArgumentException("List cannot be null");
        }
        int[] techIntList = new int[techStringList.length];
        HashMap<String, Integer> stringToCodeMap = getTechStringToCodeMap();
        for (int i = 0; i < techStringList.length; i++) {
            Integer code = stringToCodeMap.get(techStringList[i]);

            if (code == null) {
                throw new IllegalArgumentException("Unknown tech type " + techStringList[i]);
            }

            techIntList[i] = code.intValue();
        }
        return techIntList;
    }

    private static HashMap<String, Integer> getTechStringToCodeMap() {
        HashMap<String, Integer> techStringToCodeMap = new HashMap<String, Integer>();

        techStringToCodeMap.put(IsoDep.class.getName(), TagTechnology.ISO_DEP);
        techStringToCodeMap.put(MifareClassic.class.getName(), TagTechnology.MIFARE_CLASSIC);
        techStringToCodeMap.put(MifareUltralight.class.getName(), TagTechnology.MIFARE_ULTRALIGHT);
        techStringToCodeMap.put(Ndef.class.getName(), TagTechnology.NDEF);
        techStringToCodeMap.put(NdefFormatable.class.getName(), TagTechnology.NDEF_FORMATABLE);
        techStringToCodeMap.put(NfcA.class.getName(), TagTechnology.NFC_A);
        techStringToCodeMap.put(NfcB.class.getName(), TagTechnology.NFC_B);
        techStringToCodeMap.put(NfcF.class.getName(), TagTechnology.NFC_F);
        techStringToCodeMap.put(NfcV.class.getName(), TagTechnology.NFC_V);
        techStringToCodeMap.put(NfcBarcode.class.getName(), TagTechnology.NFC_BARCODE);

        return techStringToCodeMap;
    }

    /**
     * For use by NfcService only.
     * @hide
     */
    public int getServiceHandle() {
        return mServiceHandle;
    }

    /**
     * For use by NfcService only.
     * @hide
     */
    public int[] getTechCodeList() {
        return mTechList;
    }

    /**
     * Get the Tag Identifier (if it has one).
     * <p>The tag identifier is a low level serial number, used for anti-collision
     * and identification.
     * <p> Most tags have a stable unique identifier
     * (UID), but some tags will generate a random ID every time they are discovered
     * (RID), and there are some tags with no ID at all (the byte array will be zero-sized).
     * <p> The size and format of an ID is specific to the RF technology used by the tag.
     * <p> This function retrieves the ID as determined at discovery time, and does not
     * perform any further RF communication or block.
     * @return ID as byte array, never null
     */
    public byte[] getId() {
        return mId;
    }

    /**
     * Get the technologies available in this tag, as fully qualified class names.
     * <p>
     * A technology is an implementation of the {@link TagTechnology} interface,
     * and can be instantiated by calling the static <code>get(Tag)</code>
     * method on the implementation with this Tag. The {@link TagTechnology}
     * object can then be used to perform advanced, technology-specific operations on a tag.
     * <p>
     * Android defines a mandatory set of technologies that must be correctly
     * enumerated by all Android NFC devices, and an optional
     * set of proprietary technologies.
     * See {@link TagTechnology} for more details.
     * <p>
     * The ordering of the returned array is undefined and should not be relied upon.
     * @return an array of fully-qualified {@link TagTechnology} class-names.
     */
    public String[] getTechList() {
        return mTechStringList;
    }

    /**
     * Rediscover the technologies available on this tag.
     * <p>
     * The technologies that are available on a tag may change due to
     * operations being performed on a tag. For example, formatting a
     * tag as NDEF adds the {@link Ndef} technology. The {@link rediscover}
     * method reenumerates the available technologies on the tag
     * and returns a new {@link Tag} object containing these technologies.
     * <p>
     * You may not be connected to any of this {@link Tag}'s technologies
     * when calling this method.
     * This method guarantees that you will be returned the same Tag
     * if it is still in the field.
     * <p>May cause RF activity and may block. Must not be called
     * from the main application thread. A blocked call will be canceled with
     * {@link IOException} by calling {@link #close} from another thread.
     * <p>Does not remove power from the RF field, so a tag having a random
     * ID should not change its ID.
     * @return the rediscovered tag object.
     * @throws IOException if the tag cannot be rediscovered
     * @hide
     */
    // TODO See if we need TagLostException
    // TODO Unhide for ICS
    // TODO Update documentation to make sure it matches with the final
    //      implementation.
    public Tag rediscover() throws IOException {
        if (getConnectedTechnology() != -1) {
            throw new IllegalStateException("Close connection to the technology first!");
        }

        if (mTagService == null) {
            throw new IOException("Mock tags don't support this operation.");
        }
        try {
            Tag newTag = mTagService.rediscover(getServiceHandle());
            if (newTag != null) {
                return newTag;
            } else {
                throw new IOException("Failed to rediscover tag");
            }
        } catch (RemoteException e) {
            throw new IOException("NFC service dead");
        }
    }


    /** @hide */
    public boolean hasTech(int techType) {
        for (int tech : mTechList) {
            if (tech == techType) return true;
        }
        return false;
    }

    /** @hide */
    public Bundle getTechExtras(int tech) {
        int pos = -1;
        for (int idx = 0; idx < mTechList.length; idx++) {
          if (mTechList[idx] == tech) {
              pos = idx;
              break;
          }
        }
        if (pos < 0) {
            return null;
        }

        return mTechExtras[pos];
    }

    /** @hide */
    public INfcTag getTagService() {
        return mTagService;
    }

    /**
     * Human-readable description of the tag, for debugging.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("TAG: Tech [");
        String[] techList = getTechList();
        int length = techList.length;
        for (int i = 0; i < length; i++) {
            sb.append(techList[i]);
            if (i < length - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    /*package*/ static byte[] readBytesWithNull(Parcel in) {
        int len = in.readInt();
        byte[] result = null;
        if (len >= 0) {
            result = new byte[len];
            in.readByteArray(result);
        }
        return result;
    }

    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
        if (b == null) {
            out.writeInt(-1);
            return;
        }
        out.writeInt(b.length);
        out.writeByteArray(b);
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // Null mTagService means this is a mock tag
        int isMock = (mTagService == null)?1:0;

        writeBytesWithNull(dest, mId);
        dest.writeInt(mTechList.length);
        dest.writeIntArray(mTechList);
        dest.writeTypedArray(mTechExtras, 0);
        dest.writeInt(mServiceHandle);
        dest.writeInt(isMock);
        if (isMock == 0) {
            dest.writeStrongBinder(mTagService.asBinder());
        }
    }

    public static final Parcelable.Creator<Tag> CREATOR =
            new Parcelable.Creator<Tag>() {
        @Override
        public Tag createFromParcel(Parcel in) {
            INfcTag tagService;

            // Tag fields
            byte[] id = Tag.readBytesWithNull(in);
            int[] techList = new int[in.readInt()];
            in.readIntArray(techList);
            Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
            int serviceHandle = in.readInt();
            int isMock = in.readInt();
            if (isMock == 0) {
                tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
            }
            else {
                tagService = null;
            }

            return new Tag(id, techList, techExtras, serviceHandle, tagService);
        }

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

    /**
     * For internal use only.
     *
     * @hide
     */
    public synchronized void setConnectedTechnology(int technology) {
        if (mConnectedTechnology == -1) {
            mConnectedTechnology = technology;
        } else {
            throw new IllegalStateException("Close other technology first!");
        }
    }

    /**
     * For internal use only.
     *
     * @hide
     */
    public int getConnectedTechnology() {
        return mConnectedTechnology;
    }

    /**
     * For internal use only.
     *
     * @hide
     */
    public void setTechnologyDisconnected() {
        mConnectedTechnology = -1;
    }
}
