// Copyright(C) 2010, 2013 panacoran <panacoran@users.sourceforge.jp>
// 
// This program is part of Protra.
//
// Protra is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
// 
// $Id: GlobalData.cs 450 2013-05-25 14:32:09Z panacoran $

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

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

        /// <summary>
        /// グローバル変数のデータを読み込む。
        /// </summary>
        /// <param name="interpreter">インタープリタ</param>
        public static void Load(Interpreter interpreter)
        {
            var b = (SimulateBuiltins)interpreter.Builtins;
            var file = Path.Combine(GlobalDataPath(b.System, b.Prices.TimeFrame),
                                    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>
        public static void Save(Interpreter interpreter)
        {
            var b = (SimulateBuiltins)interpreter.Builtins;
            var dir = Path.Combine(GlobalDataPath(b.System, b.Prices.TimeFrame), 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="priceType">株価データの種類</param>
        /// <param name="code">証券コード</param>
        public static void Delete(string system, TimeFrame priceType, string code)
        {
            try
            {
                File.Delete(Path.Combine(Path.Combine(GlobalDataPath(system, priceType), code.Substring(0, 1)), code));
            }
            catch (DirectoryNotFoundException)
            {
            }
        }

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

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