using System;
using NFC.ISO7816_4;

namespace NFC
{
    /// <summary>
    /// Abstract representation of the platform specific NFC Hardware.
    /// </summary>
    public interface IHardware
    {
        /// <summary>
        /// Check if the device has nfc support.
        /// </summary>
        /// <returns>Returns true if the device supports NFC.</returns>
        bool IsAvailable();

        /// <returns>Returns all available readers.</returns>
        string[] GetReaders();

        /// <summary>
        /// Create a new reader instance from the specified id.
        /// </summary>
        /// <returns>Returns the spatform specific reader that corresponds to the id.</returns>
        /// <exception cref="ArgumentException">Invalid reader id.</exception>
        IReader OpenReader(string readerID);
    }

    public delegate void ReaderEventHandler(object sender, ICard card);

    /// <summary>
    /// Abstraction of a platform-specifc reader that can communicate with NFC cards.
    /// </summary>
    public interface IReader
    {
        /// <summary>
        /// Event that will be called when a new tag was discovered.
        /// </summary>
        event ReaderEventHandler CardDiscovered;

        /// <summary>
        /// Event that will be called when a tag that is in use gets disconnected.
        /// </summary>
        event ReaderEventHandler CardLost;

        void Start();

        void Stop();
    }

    public interface ICard
    {
        /// <summary>
        /// Connect to Smartcard
        /// </summary>
        void Connect();

        /// <summary>
        /// Disconnect from Smartcard
        /// </summary>
        void Disconnect();

        /// <summary>
        /// Transmit APDU Command to Smartcard
        /// </summary>
        /// <param name="apdu_cmd">Application Protocol Data Unit Command - ISO 7816</param>
        /// <returns>Application Protocol Data Unit Response - ISO 7816</returns>
        APDUResponse Transmit(APDUCommand apdu_cmd);
    }

    public class ReaderUnavailableException : Exception { }

    public class CardUnavailableException : Exception { }

    public class APDUException : Exception {
        public readonly byte ResponseCode;
    }
}