using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Windows.Forms;

namespace OsaGateway
{
    public class Contact
    {
        public delegate void ContactHandler();
        static public event ContactHandler ContactAdded;
        static public event ContactHandler ContactRemoved;
        static public event ContactHandler ContactUpdated;

        private Guid guid;
        private string name;
        private string phone;
        static public string xmlFile = Application.StartupPath + @"\" + @"contacts.xml";

        public Guid GUID
        {
            get { return guid; }
            set { this.guid = value; }
        }
        public string Name
        {
            get { return name; }
            set { this.name = value; }
        }
        public string Phone
        {
            get { return phone; }
            set { this.phone = value; }
        }

        public Contact()
        {

        }
        public Contact(string name, string phone)
        {
            this.name = name;
            this.phone = phone;
        }

        public bool Save()
        {
            if (guid.ToString() == "00000000-0000-0000-0000-000000000000")
            {
                this.Add();
                return true;
            }
            else
            {
                try
                {
                    XDocument xdoc = XDocument.Load(xmlFile);
                    XElement element = (from a in xdoc.Descendants("Contact")
                                        where a.Element("GUID").Value == this.guid.ToString()
                                        select a).FirstOrDefault();
                    if (element != null)
                    {
                        element.Element("Name").Value = this.name;
                        element.Element("Phone").Value = this.phone;
                        xdoc.Save(xmlFile);
                        if (ContactUpdated != null)
                            ContactUpdated();
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
        private bool Add()
        {
            XDocument xdoc;
            try
            {
                if (!File.Exists(xmlFile))
                    new XElement("Contacts").Save(xmlFile);
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                xdoc = XDocument.Load(xmlFile);
                xdoc.Element("Contacts").Add(new XElement("Contact",
                    new XElement("GUID", Guid.NewGuid().ToString()),
                    new XElement("Name", name),
                    new XElement("Phone", phone)));
                xdoc.Save(xmlFile);
                if (ContactAdded != null)
                    ContactAdded();

            }
            return true;
        }
        public bool Delete()
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                (from a in xdoc.Descendants("Contact")
                 where a.Element("GUID").Value == guid.ToString()
                 select a).FirstOrDefault().Remove();
                xdoc.Save(xmlFile);
                if (ContactRemoved != null)
                    ContactRemoved();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        static public Contact Get(Guid guid)
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                return (from a in xdoc.Descendants("Contact")
                        where a.Element("GUID").Value == guid.ToString()
                        select new Contact
                        {
                            GUID = new Guid(a.Element("GUID").Value),
                            Name = a.Element("Name").Value,
                            Phone = a.Element("Phone").Value
                        }).FirstOrDefault();
            }
            catch (Exception)
            {
                return null;
            }
        }
        static public Contact Get(string phone)
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                return (from a in xdoc.Descendants("Contact")
                        where a.Element("Phone").Value == phone
                        select new Contact
                        {
                            GUID = new Guid(a.Element("GUID").Value),
                            Name = a.Element("Name").Value,
                            Phone = a.Element("Phone").Value
                        }).FirstOrDefault();
            }
            catch (Exception)
            {
                return null;
            }
        }
        static public Contact GetByName(string name)
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                return (from a in xdoc.Descendants("Contact")
                        where a.Element("Name").Value == name
                        select new Contact
                        {
                            GUID = new Guid(a.Element("GUID").Value),
                            Name = a.Element("Name").Value,
                            Phone = a.Element("Phone").Value
                        }).FirstOrDefault();
            }
            catch (Exception)
            {
                return null;
            }
        }
        static public List<Contact> GetAll()
        {
            List<Contact> contacts = new List<Contact>();

            try
            {
                XDocument xdoc;
                xdoc = XDocument.Load(xmlFile);
                contacts = (from a in xdoc.Descendants("Contact")
                            orderby a.Element("Name").Value
                            select new Contact
                            {
                                GUID = new Guid(a.Element("GUID").Value),
                                Name = a.Element("Name").Value,
                                Phone = a.Element("Phone").Value
                            }).ToList();
            }
            catch (Exception)
            {
                return null;
            }
            return contacts;
        }
        static public List<Contact> GetAll(string nameCondition)
        {
            List<Contact> contacts = new List<Contact>();

            try
            {
                XDocument xdoc;
                xdoc = XDocument.Load(xmlFile);
                contacts = (from a in xdoc.Descendants("Contact")
                            where a.Element("Name").Value.ToLower().Contains(nameCondition.ToLower())
                            orderby a.Element("Name").Value
                            select new Contact
                            {
                                GUID = new Guid(a.Element("GUID").Value),
                                Name = a.Element("Name").Value,
                                Phone = a.Element("Phone").Value
                            }).ToList();
            }
            catch (Exception)
            {
                return null;
            }
            return contacts;
        }
        static public bool Add(string name, string phone)
        {
            XDocument xdoc;

            try
            {
                if (!File.Exists(xmlFile))
                    new XElement("Contacts").Save(xmlFile);
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                xdoc = XDocument.Load(xmlFile);
                xdoc.Element("Contacts").Add(new XElement("Contact",
                    new XElement("GUID", Guid.NewGuid()),
                    new XElement("Name", name),
                    new XElement("Phone", phone)));
                xdoc.Save(xmlFile);
                if (ContactAdded != null)
                    ContactAdded();
            }
            return true;
        }
        static public bool Delete(Guid guid)
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                (from a in xdoc.Descendants("Contact")
                 where a.Element("GUID").Value == guid.ToString()
                 select a).FirstOrDefault().Remove();
                xdoc.Save(xmlFile);
                if (ContactRemoved != null)
                    ContactRemoved();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        static public bool Delete(Guid guid, bool withoutEvent)
        {
            try
            {
                XDocument xdoc = XDocument.Load(xmlFile);
                (from a in xdoc.Descendants("Contact")
                 where a.Element("GUID").Value == guid.ToString()
                 select a).FirstOrDefault().Remove();
                xdoc.Save(xmlFile);
                if (ContactRemoved != null && withoutEvent == false)
                    ContactRemoved();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
