using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.Linq;
using TimeScheduler.Model;

namespace TimeScheduler.Domain.Impl
{
  class FileDomain : IDomain
  {
    #region Konstruktion
    private SimpleTimes allItems_ = new SimpleTimes();
    private string filename_ = string.Empty;
    private int lastKey_ = 0;

    public FileDomain()
    {
      var fi = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
      filename_ = Path.Combine(fi.DirectoryName, fi.Name + ".xmldata");

      if (File.Exists(filename_))
        Load();
      else
      {
        // Wenn nichts vorhanden, dann einen Spielsatz anlegen
        allItems_.Add(new TimeItem("Desc 01", DateTime.Now.Date.Add(TimeSpan.FromHours(0)), DateTime.Now.Date.Add(TimeSpan.FromHours(1.5)), 11, TimeItemType.Normal, ++lastKey_));
        allItems_.Add(new TimeItem("Desc 02", DateTime.Now.Date.Add(TimeSpan.FromHours(2)), DateTime.Now.Date.Add(TimeSpan.FromHours(3.5)), 12, TimeItemType.Break, ++lastKey_));
        allItems_.Add(new TimeItem("Desc 03", DateTime.Now.Date.Add(TimeSpan.FromHours(4)), DateTime.Now.Date.Add(TimeSpan.FromHours(5.5)), 13, TimeItemType.Holiday, ++lastKey_));
        allItems_.Add(new TimeItem("Desc 04", DateTime.Now.Date.Add(TimeSpan.FromHours(6)), DateTime.Now.Date.Add(TimeSpan.FromHours(7.5)), 14, TimeItemType.Ill, ++lastKey_));
        allItems_.Add(new TimeItem("Desc 05", DateTime.Now.Date.Add(TimeSpan.FromHours(8)), DateTime.Now.Date.Add(TimeSpan.FromHours(9.5)), 15, TimeItemType.Normal, ++lastKey_));
        // und direkt speichern
        Save();
      }
    }
    #endregion

    #region Hilfsfunktionen
    private void ReadList(string filePath)
    {
      var bin = new BinaryFormatter();
      using (var rd = new FileStream(filePath, FileMode.Open))
        //allItems_ = bin.Deserialize(rd) as List<TimeItem>;
        allItems_ = bin.Deserialize(rd) as SimpleTimes;
    }
    private void WriteList(string path)
    {
      var bin = new BinaryFormatter();
      using (var wr = new FileStream(path, FileMode.OpenOrCreate))
        bin.Serialize(wr, allItems_);
    }

    private void ReadListXml(string filePath)
    {
      //var xs = new XmlSerializer(typeof(List<TimeItem>));
      var xs = new XmlSerializer(typeof(SimpleTimes));
      using (var rd = new StreamReader(filePath))
        allItems_ = xs.Deserialize(rd) as SimpleTimes;
    }
    private void WriteListXml(string path)
    {
      //var xs = new XmlSerializer(typeof(List<TimeItem>));
      var xs = new XmlSerializer(typeof(SimpleTimes));
      using (StreamWriter wr = new StreamWriter(path))
        xs.Serialize(wr, allItems_);
    }

    private void Load()
    {
      ReadListXml(filename_);
      lastKey_ = allItems_.Max(x => x.Key);
    }
    private void Save()
    {
      var newFilename = filename_ + ".new";
      WriteListXml(newFilename);
      File.Delete(filename_);
      File.Move(newFilename, filename_);
    }
    #endregion

    #region IDomain
    IEnumerable<ITimeItem> IDomain.GetItems(DateTime date)
    {
      return allItems_
        .Where(x => x.From.Date == date)
        .OrderBy(x => x.From)
        .Cast<ITimeItem>();
    }
    ITimeItem IDomain.NewItem() { return new TimeItem(); }


    Dictionary<int, string> IDomain.GetCostUnits()
    {
      return new Dictionary<int, string>
      {
        { 11, "Allgemein CC1" },
        { 12, "Allgemein CC2" },
        { 13, "Allgemein CC3" },
        { 14, "Allgemein IC4" },
        { 15, "Allgemein CC5" },
        { 16, "Allgemein CC6" },
        { 17, "Allgemein CC7" },
      };
    }

    int IDomain.ElementAdded(ITimeItem timeItem)
    {
      var ti = new TimeItem(timeItem);
      ti.Key = ++lastKey_;
      allItems_.Add(ti);
      Save();
      return ti.Key;
    }
    void IDomain.ElementChanged(ITimeItem timeItem)
    {
      allItems_[timeItem.Key].Copy(timeItem);
      Save();
    }
    void IDomain.ElementRemoved(ITimeItem timeItem)
    {
      var removed = allItems_.Remove(timeItem.Key);
      if (removed)
        Save();
    }
    #endregion
  }
}
