using System;
using System.Collections.Generic;
using System.Text;
using FastReport.Utils;

namespace FastReport.Preview
{
  internal partial class SourcePages : IDisposable
  {
    #region Fields
    private readonly List<ReportPage> pages;
    private readonly PreparedPages preparedPages;
    #endregion

    #region Properties
    public int Count
    {
      get { return pages.Count; }
    }

    public ReportPage this[int index]
    {
      get { return pages[index]; }
    }
    #endregion

    #region Private Methods

    private Base CloneObjects(Base source, Base parent)
    {
      if (source is ReportComponentBase && !(source as ReportComponentBase).FlagPreviewVisible)
        return null;

      // create clone object and assign all properties from source
      string baseName = "";
      string objName;
      Base clone = Activator.CreateInstance(source.GetType()) as Base;
      using (XmlItem xml = new XmlItem())
      using (FRWriter writer = new FRWriter(xml))
      using (FRReader reader = new FRReader(null, xml))
      {
        reader.DeserializeFrom = SerializeTo.SourcePages;
        writer.SaveChildren = false;
        writer.SerializeTo = SerializeTo.SourcePages;
        writer.Write(source, clone);
        reader.Read(clone);
      }
      clone.Name = source.Name;
      clone.OriginalComponent = source;
      source.OriginalComponent = clone;
      if (clone is ReportComponentBase)
        (clone as ReportComponentBase).AssignPreviewEvents(source);
      // create alias
      objName = "Page" + pages.Count.ToString() + "." + clone.Name;
      if (clone is BandBase)
        baseName = "b";
      else if (clone is PageBase)
      {
        baseName = "page";
        objName = "Page" + pages.Count.ToString();
      }
      else
        baseName = clone.BaseName[0].ToString().ToLower();

      clone.Alias = preparedPages.Dictionary.AddUnique(baseName, objName, clone);
      source.Alias = clone.Alias;

      ObjectCollection childObjects = source.ChildObjects;
      foreach (Base c in childObjects)
      {
        CloneObjects(c, clone); 
      }
      clone.Parent = parent;
      return clone;
    }
#endregion

#region Public Methods
    public void Add(ReportPage page)
    {
      pages.Add(CloneObjects(page, null) as ReportPage);
    }

    public void RemoveLast()
    {
        pages.RemoveAt(pages.Count - 1);
    }

    public void Clear()
    {
      while (pages.Count > 0)
      {
        pages[0].Dispose();
        pages.RemoveAt(0);
      }
    }
    
    public int IndexOf(ReportPage page)
    {
      return pages.IndexOf(page);
    }
    
    public void ApplyWatermark(Watermark watermark)
    {
      foreach (ReportPage page in pages)
      {
        page.Watermark = watermark.Clone();
      }
    }
    
    public void ApplyPageSize()
    {
    }

    public void Load(XmlItem rootItem)
    {
      Clear();
      for (int i = 0; i < rootItem.Count; i++)
      {
        using (FRReader reader = new FRReader(null, rootItem[i]))
        {
          pages.Add(reader.Read() as ReportPage);
        }
      }
    }

    public void Save(XmlItem rootItem)
    {
      rootItem.Clear();
      for (int i = 0; i < pages.Count; i++)
      {
        using (FRWriter writer = new FRWriter(rootItem.Add()))
        {
          writer.Write(pages[i]);
        }
      }  
    }

    public void Dispose()
    {
      Clear();
    }
#endregion

    public SourcePages(PreparedPages preparedPages)
    {
            this.preparedPages = preparedPages;
      pages = new List<ReportPage>();
    }
  }
}
