using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using DevExpress.Office.Utils;
using iBemsDataService.Model;
using iBemsDataService.Util;
using System.Transactions;

namespace iBemsDataService.Controllers
{
 
    public class BemsMonitoringPointController : ApiController
    {
        private iBemsEntities db = new iBemsEntities();

        private const int VIRTUAL_FACILITY_UPPERBOUND = 100;

        [ActionName( "AddLocation" )]
        [ResponseType( typeof ( void ) )]
        public IHttpActionResult PostBemsMonitoringPoint( List<PointToLocation> pointToLocationList )
        {
            if ( !ModelState.IsValid )
            {
                return BadRequest( ModelState );
            }

            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString( uri.Query );
            int siteId;
            int buildingId, floorId, zoneId;
            if( int.TryParse( uriQuery.Get( "SiteId" ) , out siteId ) == false ||
                int.TryParse( uriQuery.Get( "BuildingId" ) , out buildingId ) == false )
            {
                return BadRequest("Not Found Parameters.");
            }

            int? nullableFloorId = null;
            int? nullableZoneId = null;

            if( int.TryParse( uriQuery.Get( "FloorId" ) , out floorId ) )
            {
                nullableFloorId = floorId;
                if( int.TryParse( uriQuery.Get( "ZoneId" ) , out zoneId ) )
                {
                    nullableZoneId = zoneId;
                }
            }
            //var query = db.BemsMonitoringPoint.Where( x => x.SiteId == siteId && 
            //                                               x.BuildingId == buildingId &&
            //                                               x.FloorId == nullableFloorId &&
            //                                               x.ZoneId == nullableZoneId );

            try
            {
                //foreach( var item in query )
                //{
                //    item.BuildingId = null;
                //    item.FloorId = null;
                //    item.ZoneId = null;
                //}

                foreach( var location in pointToLocationList )
                {
                    var foundQuery = db.BemsMonitoringPoint.Where( 
                        x => 
                            x.SiteId == location.SiteId && 
                            x.FacilityCode == location.FacilityCode && 
                            x.PropertyId  == location.PropertyId );

                    if( foundQuery.Any() == false )
                        continue;

                    var found = foundQuery.First();
                    found.BuildingId = location.BuildingId;
                    found.FloorId = location.FloorId;
                    found.ZoneId = location.ZoneId;
                }

                db.SaveChanges();
            }
            catch ( Exception )
            {                    
                throw;
            }


            return StatusCode( HttpStatusCode.NoContent );
        }

        [ActionName( "RemoveLocation" )]
        [ResponseType( typeof( void ) )]
        public IHttpActionResult PostBemsMonitoringPoint( List<PointToRemove> points )
        {
            if( !ModelState.IsValid )
            {
                return BadRequest( ModelState );
            }

            try
            {
                foreach( var point in points )
                {
                    var foundQuery = db.BemsMonitoringPoint.Where(
                        x =>
                            x.SiteId == point.SiteId &&
                            x.FacilityCode == point.FacilityCode &&
                            x.PropertyId == point.PropertyId );

                    if( foundQuery.Any() == false )
                        continue;

                    var found = foundQuery.First();
                    found.BuildingId = null;
                    found.FloorId = null;
                    found.ZoneId = null;
                }

                db.SaveChanges();
            }
            catch( Exception )
            {
                throw;
            }


            return StatusCode( HttpStatusCode.NoContent );
        }


        [ResponseType( typeof( void ) )]
        public IHttpActionResult DeleteBemsMonitoringPoint( List<PointToRemove> points )
        {
            if( !ModelState.IsValid )
            {
                return BadRequest( ModelState );
            }

            try
            {
                foreach( var point in points )
                {
                    var p = new BemsMonitoringPoint
                    {
                        SiteId = point.SiteId,
                        FacilityCode = point.FacilityCode,
                        PropertyId = point.PropertyId
                    };
                    db.BemsMonitoringPoint.Attach( p );
                    db.BemsMonitoringPoint.Remove( p );
                }

                db.SaveChanges();
            }
            catch( Exception )
            {
                throw;
            }


            return StatusCode( HttpStatusCode.NoContent );
        }

//        [ActionName( "ListExceptLocation" )]
        //[Queryable]
        //public IQueryable<PointWithLocation> GetBemsMonitoringPoint()
        //{
        //    var query = from p in db.BemsMonitoringPoint

        //                join facility in db.CmFacility on p.FacilityCode equals facility.FacilityCode into groupFacility
        //                from subFacility in groupFacility

        //                join b in db.CmBuilding on p.BuildingId equals b.BuildingId into groupBuilding
        //                from subBuilding in groupBuilding.DefaultIfEmpty()

        //                join z in db.CmZone on p.ZoneId equals z.ZoneId into groupZone
        //                from subZone in groupZone.DefaultIfEmpty()

        //                join f in db.CmFloor on p.FloorId equals f.FloorId into groupFloor
        //                from subFloor in groupFloor.DefaultIfEmpty()

        //                select new PointWithLocation
        //                {
        //                    SiteId = p.SiteId,
        //                    FacilityTypeId = p.FacilityTypeId,
        //                    FacilityCode = p.FacilityCode,
        //                    PropertyId = p.PropertyId,

        //                    ValueType = p.ValueType,
        //                    ServiceTypeId = p.ServiceTypeId,
        //                    FuelTypeId = p.FuelTypeId,

        //                    BuildingId = p.BuildingId ?? 0,
        //                    FloorId = p.FloorId ?? 0,
        //                    ZoneId = p.ZoneId ?? 0,

        //                    Name = p.Name,
        //                    Description = p.Description,

        //                    FacilityName = subFacility.Name,

        //                    BuildingName = (subBuilding == null) ? string.Empty : subBuilding.Name ,
        //                    ZoneName = (subZone == null) ? string.Empty : subZone.Name ,
        //                    FloorName = (subFloor == null) ? string.Empty : subFloor.Name
        //                };

        //    return query;
        //}

        private void GeneratePoints( int siteId , int facilityTypeId , int facilityCode )
        {
            try
            {

                var realFacilityTypeId = (from f in db.CmFacility
                                          where f.SiteId == siteId && f.FacilityCode == facilityCode && f.IsUse == true
                                          select f.FacilityTypeId).FirstOrDefault();

                if (realFacilityTypeId != 0) { facilityTypeId = realFacilityTypeId; }

                var queryToDeleteParam = from p in db.BemsFormulaParameter
                                    where p.SiteId == siteId && p.ParameterFacilityCode == facilityCode
                                    select p;
                new QueryManager<BemsFormulaParameter>(db).Delete(db.BemsFormulaParameter, queryToDeleteParam);

                
                var queryToDeletePoint = from p in db.BemsMonitoringPoint
                                    where p.SiteId == siteId && p.FacilityCode == facilityCode
                                    select p;
                new QueryManager<BemsMonitoringPoint>(db).Delete(db.BemsMonitoringPoint, queryToDeletePoint);

                


                var query = from p in db.BemsMonitoringPointBaseData
                            //where p.SiteId == siteId && p.FacilityTypeId == facilityTypeId
                            where p.FacilityTypeId == facilityTypeId
                            select p;

                foreach ( var p in query )
                {
                    var point = new BemsMonitoringPoint
                    {
                        //SiteId = p.SiteId,
                        SiteId = siteId,
                        FacilityTypeId = p.FacilityTypeId,
                        PropertyId = p.PropertyId,
                        ValueType = p.ValueType,
                        //IsAccumulated = p.IsAccumulated, 2015 04 28 삭제  hcLee
                        ServiceTypeId = p.ServiceTypeId,
                        FuelTypeId = p.FuelTypeId,
                        Name = p.Name,
                        Description = p.Description,
                        FacilityCode = facilityCode
                    };
                    db.BemsMonitoringPoint.Add( point );
                }
            }
            catch(Exception) 
            {
                // TODO : 관제점 전체 생성중 오류 발생
                // TODO : 삭제 명령이 실행되지 않아 트랜잭션 롤백된 것으로 보임
                throw;
            }
        }

        [ActionName( "Generation" )]
        [ResponseType( typeof( void ) )]
        public IHttpActionResult PostBemsMonitoringPoint( GenerationPointInfo info )
        {
            if( !ModelState.IsValid )
            {
                return BadRequest( ModelState );
            }

            try
            {
                using (var transaction = new TransactionScope(TransactionScopeOption.Required ,
                    new System.TimeSpan(0,30,0)))
                {
                    if ( info.FacilityTypeId == null )
                    {
                        var query = from f in db.CmFacility
                            where f.FacilityCode > VIRTUAL_FACILITY_UPPERBOUND
                            select new
                            {
                                SiteId = f.SiteId ,
                                FacilityTypeId = f.FacilityTypeId ,
                                FacilityCode = f.FacilityCode
                            };

                        foreach ( var f in query )
                        {
                            GeneratePoints( f.SiteId , f.FacilityTypeId , f.FacilityCode );
                        }
                    }
                    else
                    {
                        GeneratePoints( info.SiteId , info.FacilityTypeId.Value , info.FacilityCode.Value );
                    }

                    db.SaveChanges();
                    transaction.Complete();
                }
            }
            catch( Exception )
            {
                throw;
            }

            return StatusCode( HttpStatusCode.NoContent );
        }


        [ActionName("AddZoneTempHumiSet")]
        [ResponseType(typeof(void))]
        public IHttpActionResult AddZoneTempHumi (CmZoneTempHumiSet data)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
/*
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);
            int siteId;
            int buildingId, floorId, zoneId;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false)
            {
                return BadRequest("Not Found Parameters.");
            }

            int? nullableFloorId = null;
            int? nullableZoneId = null;

            if (int.TryParse(uriQuery.Get("FloorId"), out floorId))
            {
                nullableFloorId = floorId;
                if (int.TryParse(uriQuery.Get("ZoneId"), out zoneId))
                {
                    nullableZoneId = zoneId;
                }
            }*/

            try
            {
                using (var transaction = new TransactionScope())
                {
                    var newData = db.CmZoneTempHumiSet.Add(new CmZoneTempHumiSet 
                    {
                        SiteId = data.SiteId,
                        BuildingId = data.BuildingId,
                        FloorId = data.FloorId,
                        ZoneId = data.ZoneId,
                        T1 = 20, T2 = 20, T3 = 20, T4 = 20, T5 = 20, T6 = 20, T7 = 20, T8 = 20,T9 = 20,T10 = 20, T11 = 20, T12 = 20,
                        H1 = 40, H2 = 40, H3 = 40, H4 = 40, H5 = 40, H6 = 40, H7 = 40, H8 = 40, H9 = 40, H10 = 40, H11 = 40, H12 = 40,
                    });
                    db.SaveChanges();

                    transaction.Complete();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return StatusCode(HttpStatusCode.NoContent);
        }

        [ActionName("RemoveZoneTempHumiSet")]
        [ResponseType(typeof(void))]
        public IHttpActionResult RemoveZoneTempHumiSet(CmZoneTempHumiSet data)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                /*var foundQuery = db.CmZoneTempHumiSet.Where(x =>
                            x.SiteId == data.SiteId && x.BuildingId == data.BuildingId &&
                            x.FloorId == data.FloorId && x.ZoneId == data.ZoneId);
                                 if (foundQuery.Any() == false)
                {
                    var found = foundQuery.First();
                    db.CmZoneTempHumiSet.Remove(found);
                    db.SaveChanges();
                }
                 */

                var foundQuery = from x  in db.CmZoneTempHumiSet where 
                            x.SiteId == data.SiteId && x.BuildingId == data.BuildingId &&
                            x.FloorId == data.FloorId && x.ZoneId == data.ZoneId select x;

                new QueryManager<CmZoneTempHumiSet>(db).Delete(db.CmZoneTempHumiSet, foundQuery);

                db.SaveChanges();
            }
            catch (Exception)
            {
                throw;
            }
            return StatusCode(HttpStatusCode.NoContent);
        }

        [ActionName("RemovePatrolGroupUser")]
        [ResponseType(typeof(void))]
        //public IHttpActionResult RemovePatrolGroupUser(CmUser data)
        public int RemovePatrolGroupUser(CmUser data)
        {
            int ret = -1;
            if (!ModelState.IsValid)
            {
                //return BadRequest(ModelState);
                return -1;
            }

            try
            {
                IEnumerable<CmPatrolGroupUser> user = (from d in db.CmPatrolGroupUser
                                                             where d.SiteId == data.SiteId && d.UserId == data.UserId select d);
                ret = user.Count();
                if (ret > 0)
                {
                    string sqlDel = String.Format("delete from CmPatrolGroupUser where SiteId = {0} and UserId = '{1}'", data.SiteId, data.UserId);
                    db.Database.ExecuteSqlCommand(sqlDel);
                    db.SaveChanges();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return ret;
        }

        [ActionName("AddAirTempSet")] // 2015 07 29 공조기 등록시 공조기 설정온도 테이블에도 추가 한다. hcLee
        [ResponseType(typeof(void))]
        public IHttpActionResult AddZoneTempHumi(CmFacilityTempSet data)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            try
            {
                using (var transaction = new TransactionScope())
                {
                    var newData = db.CmFacilityTempSet.Add(new CmFacilityTempSet
                    {
                        SiteId = data.SiteId,
                        FacilityCode = data.FacilityCode,
                        T1 = 20,
                        T2 = 20,
                        T3 = 20,
                        T4 = 20,
                        T5 = 20,
                        T6 = 20,
                        T7 = 20,
                        T8 = 20,
                        T9 = 20,
                        T10 = 20,
                        T11 = 20,
                        T12 = 20,
                    });
                    db.SaveChanges();

                    transaction.Complete();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return StatusCode(HttpStatusCode.NoContent);
        }

        [ActionName("RemoveAirTempSet")]
        [ResponseType(typeof(void))]
        public IHttpActionResult RemoveAirTempSet(CmFacilityTempSet data)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                var foundQuery = from x in db.CmFacilityTempSet
                                 where
                                     x.SiteId == data.SiteId && x.FacilityCode == data.FacilityCode
                                 select x;

                new QueryManager<CmFacilityTempSet>(db).Delete(db.CmFacilityTempSet, foundQuery);

                db.SaveChanges();
            }
            catch (Exception)
            {
                throw;
            }
            return StatusCode(HttpStatusCode.NoContent);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

        [ActionName("CheckSameEquipCodeType")]
        public int PostCheckSameEquipCodeType(FmsEquipmentCodeType param)
        {
            IEnumerable<FmsEquipmentCodeType> newKeyData = (from data in db.FmsEquipmentCodeType
                                                            where data.SiteId == param.SiteId && data.Name == param.Name
                                                            select data).Take(1);
            if (newKeyData.Count() > 0)
            {
                //return BadRequest("중복된 이름이나 별명이 이미 존재 합니다!");
                return 1;
            }
            return 0;
        }

        [ActionName("GetMaxPropertyId")]
        public int PostGetMaxPropertyId(GetMaxPropertyId_Param param)
        {
            IEnumerable<BemsMonitoringPoint> newKeyData = (from data in db.BemsMonitoringPoint
                                                           where data.SiteId == param.SiteId && data.FacilityCode == param.FacilityCode
                                                           orderby data.PropertyId descending
                                                           select data).Take(1);

            if (newKeyData == null) return 1;

            if (newKeyData.Count() == 0)
            {
                return 1;
            }
            BemsMonitoringPoint tf = newKeyData.First();

            return tf.PropertyId + 1;
        }

        [ActionName("GetMaxSiteId")]
        public int PostGetMaxSiteId()
        {
            IEnumerable<CmSite> newKeyData = (from data in db.CmSite orderby data.SiteId descending select data).Take(1);

            if (newKeyData == null) return 1;

            if (newKeyData.Count() == 0)
            {
                return 1;
            }
            CmSite tf = newKeyData.First();

            return tf.SiteId + 1;
        }

    }

    public class GenerationPointInfo
    {
        public int SiteId { get; set; }
        public Nullable<int> FacilityTypeId { get; set; }
        public Nullable<int> FacilityCode { get; set; }
    };

    public class PointToRemove
    {
        public int SiteId { get; set; }
        public int FacilityCode { get; set; }
        public int PropertyId { get; set; }
    };

    public class GetMaxPropertyId_Param
    {
        public int SiteId { get; set; }
        //public Nullable<int> FacilityCode { get; set; }
        public int FacilityCode { get; set; }
    };
 
}