using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using Protra.Lib.Lang;

namespace Protra.Lib.Data
{
    /// <summary>
    /// グローバル変数のデータを操作するクラス
    /// </summary>
    public class GlobalData
    {
        static private string GlobalDataPath(string system, int mode)
        {
            return Path.Combine(Global.DirGlobalData,
                HttpUtility.UrlEncode(Path.GetFileNameWithoutExtension(system)) + "&" + mode.ToString());
        }

        /// <summary>
        /// グローバル変数のデータを読み込む。
        /// </summary>
        /// <param name="interpreter">インタープリタ</param>
        static public void Load(Interpreter interpreter)
        {
            var b = (SimulateBuiltins)interpreter.Builtins;
            var file = Path.Combine(GlobalDataPath(b.System, b.Mode),
                Path.Combine(b.Brand.Code.Substring(0, 1), b.Brand.Code));
            if (!File.Exists(file))
                return;
            using (var s = new FileStream(file, FileMode.Open))
            {
                var f = new BinaryFormatter();
                b.Index = (int)f.Deserialize(s);
                interpreter.GlobalVariableTable = (Dictionary<string, Value>)f.Deserialize(s);
            }
        }

        /// <summary>
        /// グローバル変数のデータを保存する。
        /// </summary>
        /// <param name="interpreter">インタープリタ</param>
        static public void Save(Interpreter interpreter)
        {
            var b = (SimulateBuiltins)interpreter.Builtins;
            var dir = Path.Combine(GlobalDataPath(b.System, b.Mode), b.Brand.Code.Substring(0, 1));
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            var file = Path.Combine(dir, b.Brand.Code);
            using (var s = new FileStream(file, FileMode.Create))
            {
                var f = new BinaryFormatter();
                f.Serialize(s, interpreter.Builtins.Index);
                f.Serialize(s, interpreter.GlobalVariableTable);
            }
        }

        /// <summary>
        /// 指定されたグローバル変数のデータを削除する。
        /// </summary>
        /// <param name="system">システムのファイル名</param>
        /// <param name="mode">実行モード</param>
        /// <param name="code">証券コード</param>
        static public void Delete(string system, int mode, string code)
        {
            try
            {
                File.Delete(Path.Combine(Path.Combine(GlobalDataPath(system, mode), code.Substring(0, 1)), code));
            }
            catch (DirectoryNotFoundException)
            {}
        }

        /// <summary>
        /// 指定されたグローバル変数のデータを削除する。
        /// </summary>
        /// <param name="system">システムのファイル名</param>
        /// <param name="mode">実行モード</param>
        static public void Delete(string system, int mode)
        {
            try
            {
                Directory.Delete(GlobalDataPath(system, mode), true);
            }
            catch (DirectoryNotFoundException)
            {}
        }

        /// <summary>
        /// グローバル変数のデータをすべて削除する。
        /// </summary>
        static public void DeleteAll()
        {
            Directory.Delete(Global.DirGlobalData, true);
        }
    }
}
