// WS-POS version 1.3 参照実装
// 
// 実装 version 0.6 

using System;
using System.Threading;
using System.Collections.Generic;

namespace WSPOSInitiative.Common
{
    /// <summary>
    /// セッションコンテキストのインターフェース
    /// Interface of the session context
    /// </summary>
    public interface ISessionContext
    {
        /// <summary>
        /// セッションを識別するConsumerのID
        /// ID of Consumer which identifies a session
        /// </summary>
        string ConsumerID { get; }

        /// <summary>
        /// POSのデバイス
        /// The POS device
        /// </summary>
        Microsoft.PointOfService.PosDevice Device { get; set; }

        /// <summary>
        /// POS for.NET,OpenPOSのデバイス名
        /// the device name of OpenPOS and POS for .NET
        /// </summary>
        string DeviceName { get; set; }

        /// <summary>
        /// デバイスのDataEventハンドラ
        /// ServiceDataEventを内部で呼び出す
        /// The DataEvent handler of a device. 
        /// Call ServiceDataEvent inside.
        /// </summary>
        void DeviceDataEventHandler(object sender, Microsoft.PointOfService.DataEventArgs e);

        /// <summary>
        /// デバイスのDirectIOEventハンドラ
        /// ServiceDirectIOEventを内部で呼び出す
        /// The DirectIOEvent handler of a device. 
        /// Call ServiceDirectIOEvent inside
        /// </summary>
        void DeviceDirectIOEventHandler(object sender, Microsoft.PointOfService.DirectIOEventArgs e);

        /// <summary>
        /// デバイスのErrorEventハンドラ
        /// ServiceErrorEventを内部で呼び出す
        /// The ErrorEvent handler of a device. 
        /// Call ErrorEvent inside
        /// </summary>
        void DeviceErrorEventHandler(object sender, Microsoft.PointOfService.DeviceErrorEventArgs e);

        /// <summary>
        /// デバイスのOutputCompleteEventハンドラ
        /// ServiceOutputCompleteEventを内部で呼び出す
        /// The OutputCompleteEvent handler of a device. 
        /// Call OutputCompleteEvent inside
        /// </summary>
        void DeviceOutputCompleteEventHandler(object sender, Microsoft.PointOfService.OutputCompleteEventArgs e);

        /// <summary>
        /// デバイスのStatusUpdateEventハンドラ
        /// ServiceStatusUpdateEventを内部で呼び出す
        /// The ServiceStatusUpdateEvent handler of a device. 
        /// Call ServiceStatusUpdateEvent inside
        /// </summary>
        void DeviceStatusUpdateEventHandler(object sender, Microsoft.PointOfService.StatusUpdateEventArgs e);

        /// <summary>
        /// サービスプロバイダに通知するDataEventハンドラ
        /// The DataEvent handler notified to a service provider
        /// </summary>
        event EventHandler<Microsoft.PointOfService.DataEventArgs> ServiceDataEvent;

        /// <summary>
        /// サービスプロバイダに通知するDirectIOEventハンドラ
        /// The DirectIOEvent handler notified to a service provider
        /// </summary>
        event EventHandler<Microsoft.PointOfService.DirectIOEventArgs> ServiceDirectIOEvent;

        /// <summary>
        /// サービスプロバイダに通知するErrorEventハンドラ
        /// The ErrorEvent handler notified to a service provider
        /// </summary>
        event EventHandler<Microsoft.PointOfService.DeviceErrorEventArgs> ServiceErrorEvent;

        /// <summary>
        /// サービスプロバイダに通知するOutputCompleteEventハンドラ
        /// The OutputCompleteEvent handler notified to a service provider
        /// </summary>
        event EventHandler<Microsoft.PointOfService.OutputCompleteEventArgs> ServiceOutputCompleteEvent;

        /// <summary>
        /// サービスプロバイダに通知するStatusUpdateEventハンドラ
        /// The StatusUpdateEvent handler notified to a service provider
        /// </summary>
        event EventHandler<Microsoft.PointOfService.StatusUpdateEventArgs> ServiceStatusUpdateEvent;

        /// <summary>
        /// 双方向通信時のコンシューマイベントポートのチャネル
        /// The channel of the consumer event port at the time of bi-directional communication
        /// </summary>
        object ConsumerEventPort { get; }

        /// <summary>
        /// このコンテキストをセッションマネージャが最後に取得した際の日時
        /// Date and time when the session manager was the last capture this context
        /// </summary>
        DateTime LastAccessDateTime { get; set; }

        /// <summary>
        /// ロングポーリング用のデバイスからのイベント待機イベント
        /// The event standby event from the device for long polling 
        /// </summary>
        IEventWait DeviceEventHappened { get; }

        /// <summary>
        /// ロングポーリング用のコンシューマからのイベントレスポンス待機イベント
        /// The event response standby event from the consumer for long polling 
        /// </summary>
        IEventWait SetEventResponseCalled { get; }

        /// <summary>
        /// ロングポーリング時に別スレッドから同じロングポーリングが呼ばれたことを
        /// 前に待機していたスレッドに通知する待機イベント
        /// The standby event to notify the thread which was waiting in front that the same long polling was called from another thread at the time of long polling.
        /// </summary>
        IEventWait OtherPollForUPOSEventCalled { get; }

        /// <summary>
        /// ロングポーリング時に別スレッドから同じロングポーリングが呼ばれた際に
        /// 前に待機していたスレッドの終了を待つための待機イベント
        /// The standby event to wait for the end of the thread which was waiting in front, when the same long polling was called from another thread at the time of long polling.
        /// </summary>
        IEventWait PreviousPollForUPOSEventEnded { get; }

        /// <summary>
        /// ロングポーリング用のデバイスイベント引数保存
        /// Save deivce event argument for long polling
        /// </summary>
        object DeviceEventArgs { get; set; }

        /// <summary>
        /// ロングポーリング用のデバイスイベント応答引数保存
        /// Save deivce event response argument for long polling
        /// </summary>
        object DeviceEventResponse { get; set; }

        /// <summary>
        /// ロングポーリング用のイベント待ち状態を示す
        /// Indicates the event waiting state for long polling
        /// </summary>
        bool IsPollingNow { get; set; }

        /// <summary>
        /// セッションが閉じられたか否かを示す
        /// That indicates whether the session is closed
        /// </summary>
        bool IsClosed { get; set; }

        /// <summary>
        /// このセッションでデバイスアクセスに用いるワーカースレッド
        /// The worker thread used for device access in this session 
        /// </summary>
        WorkerThreadHolder DeviceThread { get; set; }

        /// <summary>
        /// プロバイダのセッションタイムアウト値
        /// provider sessioin timeout
        /// </summary>
        int ProviderSessionTimeout { get; set; }

        /// <summary>
        /// ロングポーリング用のイベント待ちタイムアウト値(ミリ秒)
        /// timeout value for event long polling.
        /// </summary>
        int EventPollingTimeout { get; set; }

        /// <summary>
        /// ロングポーリング/自己ホスト両用のイベント処理終了待ちタイムアウト値(ミリ秒)
        /// timeout value for event response.
        /// </summary>
        int EventResponseTimeout { get; set; }

        /// <summary>
        /// CloseDevice時に、未削除のファイルを改めて削除するために保持する
        /// A temporary file name is held in the case of asynchronous operation for delete. 
        /// </summary>
        IList<string> TempFileNamesForDeleteWhenCloseDevice { get; }

        /// <summary>
        /// 非同期動作の際に、テンポラリファイルのアップロード先を保持する
        /// A temporary file upload uri is held in the case of asynchronous operation. 
        /// </summary>
        Queue<TempFileUploadUriPair> TempFileUploadUriPairs { get; }

        /// <summary>
        /// UPOS(OPOS)のイベントハンドリングが実行中か否かを保持する
        /// Is event handling of UPOS(OPOS) on going?
        /// </summary>
        bool UPOSEventHandlingOnGoing { get; set; }

        /// <summary>
        /// ロングポーリング用のDataContainedEvent応答引数保存
        /// Save DataContained event argument for long polling
        /// </summary>
        bool CallClearInputProperties { get; set; }

        /// <summary>
        /// ロングポーリング用のDataContainedEvent応答引数保存
        /// Save DataContained event argument for long polling
        /// </summary>
        bool SetDataEventEnabled { get; set; }

        /// <summary>
        /// DataContainedイベントリクエストに対して同時添付するプロパティ null時はDataContaindEventは発生せずDataEventが発生する
        /// DataContainedEvent including data of this properties
        /// </summary>
        IList<string> EventRequestProperties { get; set; }

        /// <summary>
        /// OpenしているデバイスがLegacy(OPOS)であるか否か
        /// Whether or not the device is a legacy (OPOS)
        /// </summary>
        bool IsLegacySO { get; set; }

        /// <summary>
        /// OPOS SO とのやりとりで 文字列をNIBBLE化する際に コードページの変換をするか否か
        /// Whether or not the code page conversion to string a NIBBLE in interacting with OPOS SO
        /// </summary>
        bool CodePageConversion { get; set; }
    }

    public class TempFileUploadUriPair 
    {
        private TempFileUploadUriPair() { }
        public TempFileUploadUriPair(string tempFileName, string uploadUri)
        {
            TempFileName = tempFileName;
            UploadUri = uploadUri;
        }

        public string TempFileName { get; private set; }
        public string UploadUri { get; private set; }
    }
}
