//ライセンス情報はAgeOnフォルダのLISENCEフォルダを参照してください

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace nispi
{
    [Serializable]
    class ThreadData
    {
        //２ｃｈでのレスの順番
        public string orderNum;
        //datのアドレス
        public string datUrl;
        //スレッドのタイトル
        public string title;
        //スレッドが作成されたＵＮＩＸ時間
        public string openTime;
        //スレッドが作成された時間
        public string openTimeString;
        //シンプルなスレッドが作成された時間
        public string simpleOpenTimeString;
        //レスの数
        public string resNum;
        //読んだレスの数
        public string readNum;
        //未読のレスの数
        public string noReadNum;
        //速度
        public string speed;
        //最終更新日時
        public string nowUnixTime;
        //このデータが書かれているファイル
        public string fileName;
        //板の日本語名
        public string boardName;
        //新しいスレッドか否か
        public bool newThread;

        public string OpenTimeString
        {
            set
            {
                this.openTimeString = value;
                string[] dateArray = this.openTimeString.Split(' ');

                this.simpleOpenTimeString = dateArray[0].Substring(2) + ' ' +  dateArray[1].Split(':')[0] + ':' + dateArray[1].Split(':')[1];
            }
        }
        public ThreadData()
        {
        }
    }
    [Serializable]
    class ThreadInfo
    {
        public List<ThreadData> threadDataList;

        public ThreadInfo()
        {
            threadDataList = new List<ThreadData>();
        }

        //クローン作製で参考に使用したサイト：http://smdn.jp/programming/netfx/cloning/
        public T CloneObject<T>(T source)
        {
            // バイナリシリアライズによってsourceの複製を作成する
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter f = new BinaryFormatter();

                f.Serialize(stream, source);

                stream.Position = 0L;

                return (T)f.Deserialize(stream);
            }
        }

        public void AddList()
        {
            ThreadData threadData = new ThreadData();

            threadData.orderNum = "";
            threadData.datUrl = "";
            threadData.title = "";
            threadData.resNum = "";
            threadData.readNum = "";
            threadData.noReadNum = "";
            threadData.openTime = "";
            threadData.speed = "";
            threadData.fileName = "";
            threadData.boardName = "";

            threadDataList.Add(threadData);
        }

        public void AddList(List<ThreadData> threadData)
        {
            threadDataList = threadDataList.Concat(threadData).ToList();
        }
        //2chのログファイル
        public void AddList(string orderNum, string datUrl, string title, string resNum, string openTime)
        {
            ThreadData threadData = new ThreadData();

            threadData.orderNum = orderNum;
            threadData.datUrl = datUrl;
            threadData.title = title;
            threadData.resNum = resNum;
            threadData.readNum = "0";
            threadData.noReadNum = "0";
            threadData.openTime = openTime;

            DateTime dtOpentime = UnixTime.GetDateTime(openTime);
            threadData.OpenTimeString = dtOpentime.ToString();

            DateTime dt = DateTime.UtcNow;
            double nowUnixTime = UnixTime.GetUnixTime(dt);
            threadData.nowUnixTime = nowUnixTime.ToString();

            double speed = (nowUnixTime - double.Parse(openTime)) / 86400.0;
            threadData.speed = Convert.ToString(Math.Truncate(speed * 100.0) / 100.0);

            string boardUrl = Util.DatUrlToBoardUrl(datUrl);
            threadData.boardName = BoardDataBase.GetName(boardUrl);
            
            threadDataList.Add(threadData);
        }
        //2chのログファイルの情報ファイルから作る
        /*public void AddList(string orderNum, string datUrl, string title, string resNum,
            string readNum, string openTime, string openTimeDateTime, string nowUnixTime, string speed, string fileName)
        {
            ThreadData threadData = new ThreadData();
            
            threadData.orderNum = orderNum;
            threadData.datUrl = datUrl;
            threadData.title = title;
            threadData.resNum = resNum;
            threadData.readNum = readNum;
            threadData.noReadNum = (Int32.Parse(resNum) - Int32.Parse(readNum)).ToString();
            threadData.openTime = openTime;
            threadData.nowUnixTime = nowUnixTime;
            threadData.OpenTimeString = openTimeDateTime;
            threadData.speed = speed;
            threadData.fileName = fileName;
            string boardUrl = Util.DatUrlToBoardUrl(datUrl);
            threadData.boardName = BoardDataBase.GetName(boardUrl);
            
            threadDataList.Add(threadData);
        }*/
        //2chのログファイルの情報ファイルから作る
        public void AddList(string orderNum, string datUrl, string title, string resNum,
            string readNum, string openTime, string openTimeDateTime, string nowUnixTime, string speed, string fileName,string boardName)
        {
            ThreadData threadData = new ThreadData();

            threadData.orderNum = orderNum;
            threadData.datUrl = datUrl;
            threadData.title = title;
            threadData.resNum = resNum;
            threadData.readNum = readNum;
            threadData.noReadNum = (Int32.Parse(resNum) - Int32.Parse(readNum)).ToString();
            threadData.openTime = openTime;
            threadData.nowUnixTime = nowUnixTime;
            threadData.OpenTimeString = openTimeDateTime;
            threadData.speed = speed;
            threadData.fileName = fileName;
            string boardUrl = Util.DatUrlToBoardUrl(datUrl);
            threadData.boardName = boardName;

            threadDataList.Add(threadData);
        }
        public void AddList(string datUrl, string title, string resNum)
        {
            ThreadData threadData = new ThreadData();

            threadData.orderNum = "0";
            threadData.datUrl = datUrl;
            threadData.title = title;
            threadData.resNum = resNum;
            threadData.readNum = "0";
            threadData.noReadNum = "0";

            try
            {
                string temp = datUrl.Substring(datUrl.LastIndexOf('/') + 1);
                threadData.openTime = temp.Substring(0, temp.LastIndexOf('.'));
            }
            catch
            {
                threadData.openTime = "0";
            }

            DateTime dtOpentime = UnixTime.GetDateTime(threadData.openTime);
            threadData.OpenTimeString = dtOpentime.ToString();

            DateTime dt = DateTime.UtcNow;
            double nowUnixTime = UnixTime.GetUnixTime(dt);

            double speed = (nowUnixTime - double.Parse(threadData.openTime)) / 86400.0;
            threadData.speed = Convert.ToString(Math.Truncate(speed * 100.0) / 100.0);

            string boardUrl = Util.DatUrlToBoardUrl(datUrl);
            threadData.boardName = BoardDataBase.GetName(boardUrl);

            threadDataList.Add(threadData);
        }
    }


    //参考ＵＲＬ
    //http://www.atmarkit.co.jp/fdotnet/dotnettips/980unixtime/unixtime.html
    class UnixTime
    {
        // UNIXエポックを表すDateTimeオブジェクトを取得
        public static DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        //現在のUNIX時間を得る（日本時間変換アリ）
        public static double GetUnixTime(DateTime targetTime)
        {
            // UNIXエポックからの経過時間を取得
            TimeSpan elapsedTime = targetTime - UNIX_EPOCH;
            TimeSpan jpTime = new TimeSpan(9, 0, 0);
            elapsedTime += jpTime;
            // 経過秒数に変換
            return (double)elapsedTime.TotalSeconds;
        }

        //現在のDateTime形式の時間を得る（日本時間変換アリ）
        public static DateTime GetDateTime(string unixTime)
        {
            double longUnixTime = double.Parse(unixTime);
            TimeSpan jpTime = new TimeSpan(9, 0, 0);
            double tempTime = Math.Round((double)jpTime.TotalSeconds, MidpointRounding.AwayFromZero);
            return UNIX_EPOCH.AddSeconds(longUnixTime + tempTime);
        }

        //現在のUNIX時間を得る（日本時間変換無し）
        public static double GetNowUnixTime(DateTime targetTime)
        {
            // UNIXエポックからの経過時間を取得
            TimeSpan elapsedTime = targetTime - UNIX_EPOCH;
            // 経過秒数に変換
            return (double)elapsedTime.TotalSeconds;
        }

        //現在の時間にX時間加えたUNIX時間を得る（日本時間変換アリ）
        public static long GetUnixTimeByPlusTime(PlusTime plusTime)
        {
            // UNIXエポックからの経過時間を取得
            TimeSpan elapsedTime = DateTime.Now - UNIX_EPOCH - new TimeSpan(9, 0, 0);
            TimeSpan plusSpan = new TimeSpan(plusTime.plusYear * 356 + plusTime.plusMonth * 31 + plusTime.plusDay, plusTime.plusHour, 0, 0);
            elapsedTime = elapsedTime - plusSpan;
            // 経過秒数に変換
            return (long)(Math.Round((double)elapsedTime.TotalSeconds, MidpointRounding.AwayFromZero));
        }

        public static string GetFileNameByPlusTime(PlusTime plusTime)
        {
            TimeSpan ts = new TimeSpan(plusTime.plusYear * 356 + plusTime.plusMonth * 31 + plusTime.plusDay, plusTime.plusHour, plusTime.plusMinute, 0);
            long longTime = ts.Ticks;
            
            DateTime dateTime = new DateTime(DateTime.Now.Ticks - longTime);

            string month = dateTime.Month.ToString();
            if (month.Length == 1) month = "0" + month;
            string day = dateTime.Day.ToString();
            if (day.Length == 1) day = "0" + day;

            return dateTime.Year.ToString() + "_" + month + "_" + day + ".txt";
        }
        public static string GetInfoFileNameByPlusTime(PlusTime plusTime)
        {
            TimeSpan ts = new TimeSpan(plusTime.plusYear * 356 + plusTime.plusMonth * 31 + plusTime.plusDay, plusTime.plusHour, plusTime.plusMinute, 0);
            long longTime = ts.Ticks;

            DateTime dateTime = new DateTime(DateTime.Now.Ticks - longTime);

            string month = dateTime.Month.ToString();
            if (month.Length == 1) month = "0" + month;
            string day = dateTime.Day.ToString();
            if (day.Length == 1) day = "0" + day;

            return dateTime.Year.ToString() + "_" + month + "_" + day + ".info.txt";
        }
        public static string GetResponseDateByPlusTime(PlusTime plusTime)
        {
            TimeSpan ts = new TimeSpan(plusTime.plusYear * 356 + plusTime.plusMonth * 31 + plusTime.plusDay, plusTime.plusHour, plusTime.plusMinute, 0);
            long longTime = ts.Ticks;

            DateTime dateTime = new DateTime(DateTime.Now.Ticks - longTime);

            string month = dateTime.Month.ToString();
            if (month.Length == 1) month = "0" + month;
            string day = dateTime.Day.ToString();
            if (day.Length == 1) day = "0" + day;
            string hour = dateTime.Hour.ToString();
            if (hour.Length == 1) hour = "0" + hour;
            string minute = dateTime.Minute.ToString();
            if (minute.Length == 1) minute = "0" + minute;
            string second = dateTime.Second.ToString();
            if (second.Length == 1) second = "0" + second;

            return dateTime.Year.ToString() + "/" + month + "/" + day + "/"
                + hour + ":" + minute + ":" + second;
        }

        public static void GetPinPointDate(string pinPointDate, ref string fromPoint, ref string toPoint)
        {
            //int pinPointYear = 0;
            //int pinPointMonth = 0;
            //int pinPointDay = 0;
            string[] data = pinPointDate.Split('_');

            // UNIXエポックからの経過時間を取得
            DateTime dateTime = new DateTime(
                int.Parse(data[0]),
                int.Parse(data[1]),
                int.Parse(data[2]),
                0,
                0,
                0);

            TimeSpan fromTm = dateTime - UNIX_EPOCH - new TimeSpan(9, 0, 0);
            TimeSpan toTm = dateTime - UNIX_EPOCH - new TimeSpan(9, 0, 0) + new TimeSpan(24, 0, 0);

            fromPoint = ((long)(Math.Round((double)fromTm.TotalSeconds, MidpointRounding.AwayFromZero))).ToString();
            toPoint = ((long)(Math.Round((double)toTm.TotalSeconds, MidpointRounding.AwayFromZero))).ToString();
        }

        public static string ChangeDateFormat(string pinPointData)
        {
            string[] data = pinPointData.Split('_');

            if (data[1].Length == 1)
                data[1] = '0' + data[1];
            if (data[2].Length == 1)
                data[2] = '0' + data[2];

            return string.Join("_", data);
        }
    }
}