/*
 * 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.technology;

import android.nfc.ErrorCodes;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import java.io.IOException;

/**
 * A high-level connection to a {@link Tag} using one of the NFC type 1, 2, 3, or 4 technologies
 * to interact with NDEF data. MiFare Classic cards that present NDEF data may also be used
 * via this class. To determine the exact technology being used call {@link #getTechnologyId()}
 *
 * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
 *
 * <p class="note"><strong>Note:</strong>
 * Use of this class requires the {@link android.Manifest.permission#NFC}
 * permission.
 */
public final class Ndef extends BasicTagTechnology {
    private static final String TAG = "NFC";

    /** @hide */
    public static final int NDEF_MODE_READ_ONLY = 1;
    /** @hide */
    public static final int NDEF_MODE_READ_WRITE = 2;
    /** @hide */
    public static final int NDEF_MODE_UNKNOWN = 3;

    /** @hide */
    public static final String EXTRA_NDEF_MSG = "ndefmsg";

    /** @hide */
    public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";

    /** @hide */
    public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";

    /** @hide */
    public static final String EXTRA_NDEF_TYPE = "ndeftype";

    //TODO: consider removing OTHER entirely - and not allowing Ndef to
    // enumerate for tag types outside of (NFC Forum 1-4, MifareClassic)
    public static final int OTHER = -1;
    public static final int NFC_FORUM_TYPE_1 = 1;
    public static final int NFC_FORUM_TYPE_2 = 2;
    public static final int NFC_FORUM_TYPE_3 = 3;
    public static final int NFC_FORUM_TYPE_4 = 4;
    public static final int MIFARE_CLASSIC = 105;

    private final int mMaxNdefSize;
    private final int mCardState;
    private final NdefMessage mNdefMsg;
    private final int mNdefType;

    /**
     * Internal constructor, to be used by NfcAdapter
     * @hide
     */
    public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
        super(adapter, tag, tech);
        if (extras != null) {
            mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
            mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
            mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG);
            mNdefType = extras.getInt(EXTRA_NDEF_TYPE);
        } else {
            throw new NullPointerException("NDEF tech extras are null.");
        }

    }

    /**
     * Get the primary NDEF message on this tag. This data is read at discovery time
     * and does not require a connection.
     */
    public NdefMessage getCachedNdefMessage() {
        return mNdefMsg;
    }

    /**
     * Get optional extra NDEF messages.
     * Some tags may contain extra NDEF messages, but not all
     * implementations will be able to read them.
     */
    public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException {
        throw new UnsupportedOperationException();
    }

    /**
     * Get NDEF tag type.
     * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
     * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
     * {@link #MIFARE_CLASSIC} or {@link #OTHER}.
     * <p>Platforms of this API revision will always return one of the above
     * values. Platforms at future API revisions may return other values, which
     * can be treated as {@link #OTHER} by applications targeting this API.
     * <p>Android devices with NFC support must always correctly enumerate
     * NFC Forum tag types, and may optionally enumerate
     * {@link #MIFARE_CLASSIC} since it requires proprietary technology.
     * Devices that cannot enumerate {@link #MIFARE_CLASSIC} will use
     * {@link #OTHER} instead.
     */
    public int getType() {
        return mNdefType;
    }

    /**
     * Get maximum NDEF message size in bytes
     */
    public int getMaxSize() {
        return mMaxNdefSize;
    }

    /**
     * Provides a hint on whether writes are likely to succeed.
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * @return true if write is likely to succeed
     */
    public boolean isWritable() {
        return (mCardState == NDEF_MODE_READ_WRITE);
    }

    // Methods that require connect()
    /**
     * Get the primary NDEF message on this tag. This data is read actively
     * and requires a connection.
     */
    public NdefMessage getNdefMessage() throws IOException, FormatException {
        checkConnected();

        try {
            int serviceHandle = mTag.getServiceHandle();
            if (mTagService.isNdef(serviceHandle)) {
                NdefMessage msg = mTagService.ndefRead(serviceHandle);
                if (msg == null) {
                    int errorCode = mTagService.getLastError(serviceHandle);
                    switch (errorCode) {
                        case ErrorCodes.ERROR_IO:
                            throw new IOException();
                        case ErrorCodes.ERROR_INVALID_PARAM:
                            throw new FormatException();
                        default:
                            // Should not happen
                            throw new IOException();
                    }
                }
                return msg;
            } else {
                return null;
            }
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service dead", e);
            return null;
        }
    }

    /**
     * Overwrite the primary NDEF message
     * @throws IOException
     */
    public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
        checkConnected();

        try {
            int serviceHandle = mTag.getServiceHandle();
            if (mTagService.isNdef(serviceHandle)) {
                int errorCode = mTagService.ndefWrite(serviceHandle, msg);
                switch (errorCode) {
                    case ErrorCodes.SUCCESS:
                        break;
                    case ErrorCodes.ERROR_IO:
                        throw new IOException();
                    case ErrorCodes.ERROR_INVALID_PARAM:
                        throw new FormatException();
                    default:
                        // Should not happen
                        throw new IOException();
                }
            }
            else {
                throw new IOException("Tag is not ndef");
            }
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service dead", e);
        }
    }

    /**
     * Attempt to write extra NDEF messages.
     * Implementations may be able to write extra NDEF
     * message after the first primary message, but it is not
     * guaranteed. Even if it can be written, other implementations
     * may not be able to read NDEF messages after the primary message.
     * It is recommended to use additional NDEF records instead.
     *
     * @throws IOException
     */
    public void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException {
        checkConnected();

        throw new UnsupportedOperationException();
    }

    /**
     * Indicates whether a tag can be made read-only with
     * {@link #makeReadonly()}
     */
    public boolean canMakeReadonly() {
        if (mNdefType == NFC_FORUM_TYPE_1 || mNdefType == NFC_FORUM_TYPE_2) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Sets the CC field to indicate this tag is read-only
     * and permanently sets the lock bits to prevent any further NDEF
     * modifications.
     * This is a one-way process and can not be reverted!
     * @throws IOException
     */
    public boolean makeReadonly() throws IOException {
        checkConnected();

        try {
            int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle());
            switch (errorCode) {
                case ErrorCodes.SUCCESS:
                    return true;
                case ErrorCodes.ERROR_IO:
                    throw new IOException();
                case ErrorCodes.ERROR_INVALID_PARAM:
                    return false;
                default:
                    // Should not happen
                    throw new IOException();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "NFC service dead", e);
            return false;
        }
    }

    @Override
    public byte[] transceive(byte[] data) {
        checkConnected();

        throw new UnsupportedOperationException();
    }
}
