using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Xml.Linq;

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace KsiegaGosciMVC.Models
{
    //Struktura opisująca elementarny typ danych (klasa encji)
    public struct Wpis
    {
        private string nazwaUżytkownika;
        private string treść;
        private DateTime data;
        private string adresIP;

        [Required(ErrorMessage="Wymagane jest podanie nazwy użytkownika")]
        [StringLength(256,MinimumLength=1,ErrorMessage="Niepoprawna długość nazwy użytkownika")]
        [RegularExpression(@"[a-zA-Z0-9'.ąćęłńóśżź\s]{1,256}",ErrorMessage="Nazwa użytkowniak zawiera niepoprawne znaki")]
        [DisplayName("Nazwa użytkownika")]
        public string NazwaUżytkownika { get { return nazwaUżytkownika; } }

        [Required(ErrorMessage = "Wymagane jest podanie treści")]
        [StringLength(1024, MinimumLength = 1, ErrorMessage = "Niepoprawna długość wpisu")]
        [RegularExpression(@"[a-zA-Z0-9'.ąćęłńóśżź\s]{1,1024}", ErrorMessage = "Wpis zawiera niepoprawne znaki")]
        [DisplayName("Treść wpisu")]
        public string Treść { get { return treść; } }

        [Required]
        public DateTime Data { get { return data; } }

        [Required]
        public string AdresIP { get { return adresIP; } }

        public Wpis(string nazwaUżytkownika, string treść, DateTime data, string adresIP)
        {
            this.nazwaUżytkownika = nazwaUżytkownika;
            this.treść = treść; ;
            this.data = data;
            this.adresIP = adresIP;
        }
    }

    //Model księgi gości. Tu zapisana jest logika biznesowa aplikacji
    public class Wpisy
    {
        List<Wpis> wpisy = new List<Wpis>();

        public bool ZapiszDoPlikuPoKażdymDodaniuWpisu = true;

        public void Dodaj(Wpis nowyWpis)
        {
            wpisy.Add(nowyWpis);
            if (ZapiszDoPlikuPoKażdymDodaniuWpisu) ZapiszDoPlikuXml();
        }
        
        public int Ilość
        {
            get
            {
                return wpisy.Count;
            }
        }

        public Wpis this[int i]
        {
            get
            {
                return wpisy[i];
            }
        }        

        public bool ZapiszDoPlikuXml(string nazwaPlikuXml = null)
        {
            if (nazwaPlikuXml == null) nazwaPlikuXml = this.nazwaPlikuXml;

            try
            {
                if (System.IO.File.Exists(nazwaPlikuXml)) System.IO.File.Copy(nazwaPlikuXml, nazwaPlikuXml + ".bak", true);

                XDocument xml = new XDocument(
                    new XDeclaration("1.0", "utf-8", "yes"),
                    new XElement("Wpisy",
                        new XElement("DataZapisu", DateTime.Now.ToString()),
                        from wpis in wpisy
                        select new XElement("Wpis",
                            new XElement("NazwaUżytkownika", wpis.NazwaUżytkownika),
                            new XElement("Treść", wpis.Treść),
                            new XElement("Data", wpis.Data),
                            new XElement("AdresIP", wpis.AdresIP)
                        )
                    )
                );

                xml.Save(nazwaPlikuXml);
                //Global.DopiszDoPlikuLog("Zapis prawidłowy");
                return true;
            }
            catch(Exception exc)
            {
                //Global.DopiszDoPlikuLog(exc.Message);
                return false;
            }
        }

        private bool CzytajZPlikuXml(string nazwaPlikuXml)
        {
            try
            {
                XDocument xml = XDocument.Load(nazwaPlikuXml);

                IEnumerable<Wpis> odczytaneWpisy =
                    from wpis in xml.Descendants("Wpis")
                    select
                       new Wpis(
                           wpis.Element("NazwaUżytkownika").Value,
                           wpis.Element("Treść").Value,
                           DateTime.Parse(wpis.Element("Data").Value),
                           wpis.Element("AdresIP").Value);

                wpisy.Clear();
                wpisy.AddRange(odczytaneWpisy);

                return true;
            }
            catch
            {
                return false;
            }
        }

        string nazwaPlikuXml;

        public Wpisy(string nazwaPlikuXml)
        {
            this.nazwaPlikuXml = nazwaPlikuXml;
            CzytajZPlikuXml(nazwaPlikuXml);
        }
    }
}