using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;

namespace FactoriesWeb
{
    public class DataBase
    {
        public List<Factory> Factories { get; set; }
        public List<Office> Offices { get; set; }
        public List<Store> Stores { get; set; }
        public List<Product> Products { get; set; }
        public double OfficeStoreDistance { get; set; }

        public DataBase()
        {
            Factories = new List<Factory>();
            Offices = new List<Office>();
            Stores = new List<Store>();
            Products = new List<Product>();
            OfficeStoreDistance = 100000;
        }

        public static DataBase GetInstance(HttpContext context)
        {
            var dataBase = context.Session["DataBase"] as DataBase;
            if (dataBase == null)
            {
                var path = context.Server.MapPath("database.xml");
                if (File.Exists(path))
                {
                    var serializer = new XmlSerializer(typeof(DataBase));
                    using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
                    {
                        dataBase = (DataBase)serializer.Deserialize(stream);
                    }
                }
                else
                {
                    dataBase = new DataBase();
                }
                context.Session["DataBase"] = dataBase;
            }
            dataBase.CalculateStoreNumbers();
            return dataBase;
        }

        void CalculateStoreNumbers()
        {
            foreach (var office in Offices)
            {
                office.Stores = Stores.Count(s => Distance(s.Longitude, s.Latitude, office.Longitude, office.Latitude) < OfficeStoreDistance);
            }
        }

        public double Distance(double lat1, double long1, double lat2, double long2)
        {
            var R = 6371000.0; // m
            var dLat = (lat2 - lat1) * (Math.PI / 180);
            var dLon = (long2 - long1) * (Math.PI / 180);
            var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                    Math.Cos(lat1 * (Math.PI / 180)) * Math.Cos(lat2 * (Math.PI / 180)) *
                    Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            return R * c;
        }
    }
}
