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 iBemsDataService.Controllers.Bems.Common;
using iBemsDataService.Controllers.Bems.ScheduledTask;
using System.Diagnostics;
using System.Transactions;
using System.Collections.Specialized;

namespace iBemsDataService.Controllers
{
    public class BemsMonitoringPointHistoryController : ApiController
    {
        private iBemsEntities db;
        private PointHistoryValueManager pointHistoryValueManager;
        private Boolean IS_DEBUG = false;

        //static private List<MonitoringPointSType> m_listSType = new List<MonitoringPointSType>(); // 2016 09 19
        //private List<MonitoringPointSType> m_listSType;

        //static private List<CalculationValueSType[]> m_valuesListMonth = new List<CalculationValueSType[]>();
        //static private List<CalculationValueSType[]> m_valuesListDay = new List<CalculationValueSType[]>();

        //private String debugPath = "e:\\monitoring.txt";

        public BemsMonitoringPointHistoryController()
        {
            db = new iBemsEntities();
            pointHistoryValueManager = new PointHistoryValueManager( db );
            debug();
        }

        private void debug()
        {
            if (IS_DEBUG)
            {
                //var listener = new TextWriterTraceListener(debugPath);
                //Trace.Listeners.Add(listener);
                //Trace.AutoFlush = true;
            }
        }

        [ActionName( "Location" )]
        public CalculationValue[] GetBemsMonitoringPointHistory()
        {
/*            ControlBems bemsJob = new ControlBems();
            bemsJob.Execute(null); */

            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString( uri.Query );

            string uriTimeIntervalType = uriQuery.Get( "TimeIntervalType" );
            string uriStartDate = uriQuery.Get( "StartDate" );
            string uriEndDate = uriQuery.Get( "EndDate" );

            int siteId;
            int buildingId = -1; int fuelTypeId = -1;
            int floorId, zoneId, timeInterval = -1;
            DateTime startDate, endDate;
            if( int.TryParse( uriQuery.Get( "SiteId" ) , out siteId ) == false ||
                int.TryParse( uriQuery.Get( "BuildingId" ) , out buildingId ) == false ||
                int.TryParse( uriTimeIntervalType , out timeInterval ) == false ||
                DateTime.TryParse( uriStartDate , out startDate ) == false ||
                DateTime.TryParse( uriEndDate , out endDate ) == false ||
                int.TryParse( uriQuery.Get( "FuelTypeId" ) , out fuelTypeId ) == false )
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, buildingId, uriTimeIntervalType, uriStartDate, uriEndDate, fuelTypeId));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            if (buildingId == 0) // 사이트 전체면 사이트 전체가 있는 지 먼저 확인 하고 아닌 경우 건물들 합을 구한다.
            {
                IQueryable<MonitoringPoint> querySite;
                querySite = from p in db.BemsMonitoringPoint where p.SiteId == siteId && p.BuildingId == 0 && p.FuelTypeId == fuelTypeId
                            select new MonitoringPoint
                {
                    SiteId = p.SiteId,
                    FacilityCode = p.FacilityCode ,
                    PropertyId = p.PropertyId ,
                };

                if (querySite != null && querySite.Count() > 0)
                {
                    list = querySite.ToList();
                }
                else
                {
                    IQueryable<CmBuilding> query;
                    query = from x in db.CmBuilding where x.SiteId == siteId select x;
                    foreach (CmBuilding b in query)
                    {
                        AddPointToListInLocation(list, siteId, fuelTypeId, b.BuildingId, null, null);
                    }
                }
            }
            else
            {
                AddPointToListInLocation(list, siteId, fuelTypeId, buildingId, nullableFloorId, nullableZoneId);
            }
            
            try
            {
                //AddPointToListInLocation( list , siteId, fuelTypeId , buildingId , nullableFloorId , nullableZoneId );
                var values = CreateCalculationValues( startDate , endDate , timeIntervalType );
                foreach( var point in list )
                {
                    var pointValues = pointHistoryValueManager.GetPointValues( 
                        siteId , point.FacilityCode , point.PropertyId , 
                        timeIntervalType , startDate , endDate );

                    if( pointValues == null )
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for( var i = 0 ; i < values.Length ; i++ )
                    {
                        v = values[i];
                        if( p == null )
                        {
                            if( pointValues.Length <= index ) break;

                            p = pointValues[index];
                        }

                        if( p.DateTime == v.DateTime )
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if( pointValues.Length <= index ) break;
                        }
                    }
                }
                return values;
            }
            catch( Exception )
            {
                throw;
            }

        }

        //[ActionName("ServiceType")]           //
        /*public CalculationValueSType[] GetBemsMonitoringPointHistoryService()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId, floorId, zoneId, fuelTypeId, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2}",
                    uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPointSType> list = new List<MonitoringPointSType>();

            if (buildingId == 0)
            {
                IQueryable<CmBuilding> query;
                query = from x in db.CmBuilding where x.SiteId == siteId select x;
                foreach (CmBuilding b in query)
                {
                    //AddPointToListInLocationSType(list, siteId, fuelTypeId, b.BuildingId, null, null);                        
                    AddPointToListInLocationSType_New(list, siteId, fuelTypeId, b.BuildingId);
                }
            }
            else
            {
                //AddPointToListInLocationSType(list, siteId, fuelTypeId, buildingId, nullableFloorId, nullableZoneId);
                AddPointToListInLocationSType_New(list, siteId, fuelTypeId, buildingId);
            }

            try
            {
                var values = CreateCalculationValuesSType(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(siteId, point.FacilityCode, point.PropertyId, timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValueSType v = null;
                    for (var i = point.ServiceTypeId - 1; i < values.Length; i +=12)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) 
                                break;

                            p = pointValues[index];
                        }

                        //if (p.DateTime == v.DateTime && point.ServiceTypeId == v.ServiceType)
                        if (p.DateTime == v.DateTime)
                        {
                            //if 
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) 
                                break;
                        }
                    }
                }
                return values;
            }
            catch (Exception)
            {
                throw;
            }
        }
          */
        //DB update
        //private void MakeMonthCalcData(int siteId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate, List<CalculationValueSType[]> valuesListReturn)
        private void SaveCalcData(int siteId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate, CalculationValueSType[] valuesList)
        {
            using (var transaction = new TransactionScope())
            {
                try
                {
                    string sqlDel = (timeIntervalType == TimeInterval.Month) ? 
                        String.Format("delete from CmServiceEnergyCalcMonth where SiteId = {0} and calDate >= '{1}' and calDate < '{2}'", siteId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd")) : 
                        String.Format("delete from CmServiceEnergyCalcDay where SiteId = {0} and calDate >= '{1}' and calDate < '{2}'", siteId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"));
                    db.Database.ExecuteSqlCommand(sqlDel); 
                    
                    //db.Database.ExecuteSqlCommand("delete from CmServiceEnergyCalcMonth where SiteId = @siteId and calDate >= @start and calDate <= @end", 
                    //new SqlParameter ("@siteId", siteId), startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"));

                    if (timeIntervalType == TimeInterval.Month) // Month처리
                    {
                        foreach (var k in valuesList)
                        {
                            var newData = new CmServiceEnergyCalcMonth
                            {
                                SiteId = siteId,
                                calDate = k.DateTime,
                                ServiceTypeId = (short)k.ServiceType,
                                Value = k.Value
                            };
                            db.CmServiceEnergyCalcMonth.Add(newData);
                        }
                        db.SaveChanges();
                    }
                    else // day 처리
                    {
                        foreach (var k in valuesList)
                        {
                            var newData = new CmServiceEnergyCalcDay
                            {
                                SiteId = siteId,
                                calDate = k.DateTime,
                                ServiceTypeId = (short)k.ServiceType,
                                Value = k.Value
                            };
                            db.CmServiceEnergyCalcDay.Add(newData);
                        }
                        db.SaveChanges();
                    }
                }
                catch (Exception) { throw; }
                transaction.Complete();
            }    
        }

        //private List<CalculationValueSType[]> LoadCalcData(int siteId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate)
        private CalculationValueSType[] LoadCalcData(int siteId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate)
        {
            //List<CalculationValueSType[]> valuesListDB = new List<CalculationValueSType[]>();
            CalculationValueSType[] list;
            if (timeIntervalType == TimeInterval.Month)
            {
                list =
                    (from x in db.CmServiceEnergyCalcMonth
                     where x.SiteId == siteId && x.calDate >= startDate && x.calDate <= endDate
                     select new CalculationValueSType
                     {
                         DateTime = x.calDate,
                         ServiceType = x.ServiceTypeId,
                         Value = (double)x.Value
                     }).ToArray<CalculationValueSType>();
            }
            else
            {
                list =
                    (from x in db.CmServiceEnergyCalcDay
                     where x.SiteId == siteId && x.calDate >= startDate && x.calDate <= endDate
                     select new CalculationValueSType
                     {
                         DateTime = x.calDate,
                         ServiceType = x.ServiceTypeId,
                         Value = (double)x.Value
                     }).ToArray<CalculationValueSType>();
            }
            //valuesListDB.Add(list);
            //return valuesListDB;
            return list;
        }


        //private CalculationValueSType[] MakeCalcData(int siteId, int buildingId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate, List<CalculationValueSType[]> valuesListReturn)
        private CalculationValueSType[] MakeCalcData(List<MonitoringPointSType> listSType, int siteId, int buildingId, TimeInterval timeIntervalType, DateTime startDate, DateTime endDate) // 2017 02 22   listSType 로컬로 변경
        {
            //if (m_listSType.Count() <= 0)
            {
                if (buildingId == 0)
                {
                    IQueryable<CmBuilding> query;
                    query = from x in db.CmBuilding where x.SiteId == siteId select x;
                    foreach (CmBuilding b in query)
                    {
                        AddPointToListInLocationSType_New2(listSType, siteId, b.BuildingId);
                    }
                }
                else
                {
                    AddPointToListInLocationSType_New2(listSType, siteId, buildingId);
                }
            }

            List<CalculationValueSType[]> valuesListReturn = new List<CalculationValueSType[]>();
            if (timeIntervalType == TimeInterval.Month)
                valuesListReturn.Add(CreateCalculationValuesSType(startDate, startDate, timeIntervalType));      // startDate 2개가 맞다. 한달씩, 하기 떄문이다
            else
                valuesListReturn.Add(CreateCalculationValuesSType(startDate, endDate, timeIntervalType));

            List<CalculationValueSType[]> valuesList = new List<CalculationValueSType[]>();
            IQueryable<BemsFactorToe> queryTOE;
            queryTOE = from x in db.BemsFactorToe where x.FuelTypeId < 3 select x;
            foreach (BemsFactorToe TOE in queryTOE)
            {
                if (timeIntervalType == TimeInterval.Month)
                    valuesList.Add(CreateCalculationValuesSType(startDate, startDate, timeIntervalType)); // startDate 2개가 맞다. 한달씩, 또는 하루씩 하기 떄문이다
                else
                    valuesList.Add(CreateCalculationValuesSType(startDate, endDate, timeIntervalType));
            }

            try
            {
                foreach (var point in listSType)
                {
                    if (point.FuelTypeId <= 0) continue; // 2017 02 17 방어코드 추가
                    var pointValues = pointHistoryValueManager.GetPointValues(siteId, point.FacilityCode, point.PropertyId, timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    var values = valuesList[point.FuelTypeId - 1];

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValueSType v = null;
                    for (var i = point.ServiceTypeId - 1; i < values.Length; i += 12)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index)
                                break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index)
                                break;
                        }
                    }
                }

                foreach (BemsFactorToe TOE in queryTOE)
                {
                    int r = 0;
                    foreach (var k in valuesList[TOE.FuelTypeId - 1])
                    {
                        k.Value = k.Value * (double)TOE.kcal;
                        valuesListReturn[0][r].Value += k.Value; // 연료별이 kcal로 환산되어 합쳐졌기에 리스트 하나만 가면 된다, DB저장을 위해서도 하나가 편리하다.
                        r++;
                    }
                }

                //DB update
                DateTime currentTime = DateTime.Now;
                if (timeIntervalType == TimeInterval.Month) // 이번달이나
                {
                    currentTime = new DateTime(currentTime.Year, currentTime.Month, 1, 0, 0, 0);
                    if (startDate < currentTime)
                        SaveCalcData(siteId, timeIntervalType, startDate, endDate, valuesListReturn[0]);
                }
                else // 오늘은 DB에 쓰지 않는다. 오늘은 불려지지 않는다. -> 아예 현재달은 쓰지 않는다.
                {
                    if (currentTime.Year == startDate.Year && currentTime.Month == startDate.Month)
                    { }

                    else
                        SaveCalcData(siteId, timeIntervalType, startDate, endDate, valuesListReturn[0]);
                }
                return valuesListReturn[0]; // 연료별이 kcal로 환산되어 합쳐졌기에 리스트 하나만 가면 된다, DB저장을 위해서도 하나가 편리하다.
            }
            catch (Exception)
            {
                throw;
            }
        }
        private CalculationValueSType[] MakeCalcDataToday(List<MonitoringPointSType> listSType, int siteId, int buildingId)
        {
            //if (m_listSType.Count() <= 0)
            {
                if (buildingId == 0)
                {
                    IQueryable<CmBuilding> query;
                    query = from x in db.CmBuilding where x.SiteId == siteId select x;
                    foreach (CmBuilding b in query)
                    {
                        AddPointToListInLocationSType_New2(listSType, siteId, b.BuildingId);
                    }
                }
                else
                {
                    AddPointToListInLocationSType_New2(listSType, siteId, buildingId);
                }
            }

            //DB update
            DateTime currentTime = DateTime.Now;
            DateTime startDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 0, 0, 0);
            DateTime endDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 23, 59, 59);

            List<CalculationValueSType[]> valuesListReturn = new List<CalculationValueSType[]>();
            valuesListReturn.Add(CreateCalculationValuesSType(startDate, endDate, TimeInterval.Day));      

            List<CalculationValueSType[]> valuesList = new List<CalculationValueSType[]>();
            IQueryable<BemsFactorToe> queryTOE;
            queryTOE = from x in db.BemsFactorToe where x.FuelTypeId < 3 select x;
            foreach (BemsFactorToe TOE in queryTOE)
            {
                valuesList.Add(CreateCalculationValuesSType(startDate, endDate, TimeInterval.Day)); 
            }

            try
            {
                foreach (var point in listSType)
                {
                    if (point.FuelTypeId <= 0) continue; // 2017 02 17 방어코드 추가

                    var pointValues = pointHistoryValueManager.GetPointValues(siteId, point.FacilityCode, point.PropertyId, TimeInterval.Day, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    var values = valuesList[point.FuelTypeId - 1];

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValueSType v = null;
                    for (var i = point.ServiceTypeId - 1; i < values.Length; i += 12)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index)
                                break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index)
                                break;
                        }
                    }
                }

                foreach (BemsFactorToe TOE in queryTOE)
                {
                    int r = 0;
                    foreach (var k in valuesList[TOE.FuelTypeId - 1])
                    {
                        k.Value = k.Value * (double)TOE.kcal;
                        valuesListReturn[0][r].Value += k.Value; // 연료별이 kcal로 환산되어 합쳐졌기에 리스트 하나만 가면 된다, DB저장을 위해서도 하나가 편리하다.
                        r++;
                    }
                }

                return valuesListReturn[0]; // 연료별이 kcal로 환산되어 합쳐졌기에 리스트 하나만 가면 된다, DB저장을 위해서도 하나가 편리하다.
            }
            catch (Exception)
            {
                throw;
            }
        }

        [ActionName("ServiceType")]           //
        //public CalculationValueSType[] GetBemsMonitoringPointHistoryService()
        public List<CalculationValueSType[]> GetBemsMonitoringPointHistoryService()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId, floorId, zoneId, fuelTypeId, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2}",
                    uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPointSType> listSType = new List<MonitoringPointSType>(); // 2017 02 22  로컬로 변경

            List<CalculationValueSType[]> valuesListReturn = new List<CalculationValueSType[]>();
            CalculationValueSType[] cv = CreateCalculationValuesSType(startDate, endDate, timeIntervalType);
            // 있는지 판단해서 있으면 보낸다
            // 이번달 또는 오늘은 제외
            // 
            DateTime dtStart = new DateTime(startDate.Year, startDate.Month, startDate.Day, 0, 0, 0);
            DateTime dtEnd = new DateTime(startDate.Year, startDate.Month, startDate.Day, 23, 59, 59);

            if (timeIntervalType == TimeInterval.Month)
            {
                CalculationValueSType[] list;
                while (dtEnd < endDate)
                {
                    // 먼저 이미 DB에 있는지 보고 있으면 바로 받고
                    list = LoadCalcData(siteId, timeIntervalType, dtStart, dtEnd);
                    if (list.Length <= 0) list = MakeCalcData(listSType, siteId, buildingId, timeIntervalType, dtStart, dtStart.AddMonths(1)); // 없으면 만들고 받는다

                    foreach (CalculationValueSType s in list)
                    {
                        foreach (CalculationValueSType v in cv)
                        {
                            if (v.ServiceType == s.ServiceType && v.DateTime == s.DateTime)
                            {
                                v.Value = s.Value;
                                break;
                            }
                        }
                    }
                    dtStart = dtStart.AddMonths(1);
                    dtEnd = dtEnd.AddMonths(1);
                }
                valuesListReturn.Add(cv);
                return valuesListReturn;
            }
            else
            {
                DateTime current= DateTime.Now;
                CalculationValueSType[] list;

                // 현재달이면 오늘은 제외한다
                //dtEnd = (endDate.Year == current.Year && endDate.Month == current.Month) ? current.AddDays(-1) : endDate; 현재달의 day는 아예 안쓰기로 하면서 오늘처리는 필요 없어진다
                dtEnd = endDate;

                list = LoadCalcData(siteId, timeIntervalType, dtStart, dtEnd);
                if (list.Length <= 0) list = MakeCalcData(listSType, siteId, buildingId, timeIntervalType, dtStart, dtEnd); // 없으면 만들고 받는다. 이떄 현재달이며 오늘은 만들지 않는다.

                foreach (CalculationValueSType s in list)
                {
                    foreach (CalculationValueSType v in cv)
                    {
                        if (v.ServiceType == s.ServiceType && v.DateTime == s.DateTime)
                        {
                            v.Value = s.Value;
                            break;
                        }
                    }
                }
                                                                                     /*
                if (endDate.Year == current.Year && endDate.Month == current.Month)
                {
                    list = MakeCalcDataToday(siteId, buildingId);
                    foreach (CalculationValueSType s in list)
                    {
                        foreach (CalculationValueSType v in cv)
                        {
                            if (v.ServiceType == s.ServiceType && v.DateTime == s.DateTime)
                            {
                                v.Value = s.Value;
                                break;
                            }
                        }
                    }
                }                                                                                       */
                    //if (dtStart >= current) 
                        //break;
                //}
                valuesListReturn.Add(cv);
                return valuesListReturn;
            }
            //return valuesListReturn;
        }


        [ActionName("Location_ZoneTempHumi")]
        //public CalculationValue[] GetBemsMonitoringPointHistoryZoneTempHumi()
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryZoneTempHumi()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId = -1; int fuelTypeId = -1;
            int floorId, zoneId, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, buildingId, uriTimeIntervalType, uriStartDate, uriEndDate, fuelTypeId));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToListInLocation_ZoneTempHumi(list, siteId, buildingId, nullableFloorId, nullableZoneId);        // 2015 08 03 FType 91,92로 가려야 한다.
            // 온도를 습도들 CO2 들로 따로 처리하는 것으로 변경한다 2016 05 23


            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                /*var THSetQuery = from x in db.CmZoneTempHumiSet
                             where x.SiteId == siteId && x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == nullableZoneId
                        select x;

                ControlBems cb = new ControlBems();
                cb.GetTempSetValue(1, */

                foreach (var point in list) // 온도,습도 2개가 존재해야 한다.              + CO2 농도 (2016 04 18 추가됨  즉 3개
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;

                    var values = CreateCalculationValues(startDate, endDate, timeIntervalType); // 위치 안으로 이동 2015 08 04 hcLee

                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            //v.Value += p.Value;
                            v.Value = p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                //return values;
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
        }

        [ActionName("FacilityRunTime")]
        //public CalculationValue[] GetBemsMonitoringPointHistoryZoneTempHumi()
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryRunTime()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int facilityCode = -1, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("FacilityCode"), out facilityCode) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4}",
                    siteId, facilityCode, uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;


            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_RunTime(list, siteId, facilityCode); // 2015 08 03 FType 91,92로 가려야 한다.

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                foreach (var point in list) // 가동시간 point 한개가 존재한다.
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;

                    var values = CreateCalculationValues(startDate, endDate, timeIntervalType);

                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            //v.Value += p.Value;
                            v.Value = p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                //return values;
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
        }

        // jhLee 2016-04-22
        [ActionName("FacilityCostRunTime")]
        public List<CalculationValue> GetBemsMonitoringPointHistoryCostRunTime()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            int siteId, facilityCode = -1, timeInterval = -1;
            DateTime startDate, endDate;
            SetFacilityRunTimeParam(uriQuery, ref facilityCode, ref timeInterval, out siteId, out startDate, out endDate);
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            try
            {
                FacilityCostInfo facilityCostInfo = GetFacilityCostInfo(siteId, facilityCode);
                
                List<int> propertyIdList = GetPropertyIdList(siteId, facilityCode, (short)facilityCostInfo.FuelTypeId);

                var resultGroupByHour = GetHourRunTimeCostValues(siteId, facilityCode, propertyIdList, startDate, endDate, facilityCostInfo);
                var result = GetGroupedRuntimeCostValue(resultGroupByHour, timeIntervalType);
                return result == null ? new List<CalculationValue>() : result.ToList();
            }
            catch
            {
                return new List<CalculationValue>();
            }
            
        }

        private FacilityCostInfo GetFacilityCostInfo(int siteId, int facilityCode)
        {
            FacilityCostInfo facilityCostInfo
                = (from x in db.CmFacility
                   where x.SiteId == siteId && x.FacilityCode == facilityCode
                   select new FacilityCostInfo
                   {
                       SiteId = x.SiteId,
                       FacilityCode = x.FacilityCode,
                       FuelTypeId = x.FuelTypeId,
                       ContractType = x.ContractType,
                       RatedPowerConsumption = x.RatedPowerConsumption
                   }).First();
            CheckFacilityCostInfo(facilityCostInfo);
            return facilityCostInfo;
        }

        private static void CheckFacilityCostInfo(FacilityCostInfo facilityCostInfo)
        {
            if (facilityCostInfo.FuelTypeId == null)
            {
                throw new Exception("FuelTypeId is null");
            }
            if (facilityCostInfo.ContractType == null)
            {
                throw new Exception("ContractType is null");
            }
        }

        private void SetFacilityRunTimeParam(NameValueCollection uriQuery, ref int facilityCode, ref int timeInterval, out int siteId, out DateTime startDate, out DateTime endDate)
        {
            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("FacilityCode"), out facilityCode) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4}",
                    siteId, facilityCode, uriTimeIntervalType, uriStartDate, uriEndDate));
            }
        }

        private List<int> GetPropertyIdList(int siteId, int facilityCode, Nullable<short> fuelTypeId)
        {
            return (from x in db.BemsMonitoringPoint
                    where x.SiteId == siteId && 
                    x.FacilityCode == facilityCode &&
                    x.FuelTypeId == fuelTypeId // 원래방식인 가동시간을 이용할려면   fuelTypeId는 사용하지말고 ServiceTypeId = 120 만 이용해야 한다. 
                    //hcLee 2016 07 11 두소장 요청 가동시간계산이 아닌 전력량 계산으로 변경
                    && x.ServiceTypeId > 0 && x.ServiceTypeId < 100  && x.BuildingId > 0
                    select x.PropertyId).ToList();
        }

        private IQueryable<CalculationValue> GetHourRunTimeCostValues(int siteId, int facilityCode, List<int> propertyIdList, DateTime startDate, DateTime endDate, FacilityCostInfo facilityCostInfo)
        {
            short fuelTypeId = (short)facilityCostInfo.FuelTypeId;
            short contractType = (short)facilityCostInfo.ContractType;
            string ratedPowerConsumption = facilityCostInfo.RatedPowerConsumption == null ? "" : facilityCostInfo.RatedPowerConsumption;

            // DateTime기준으로 묶은 시간별 모니터링 관제점 기록
            var query
                = (from x in db.BemsMonitoringPointHistoryHourly
                   where
                       x.SiteId == siteId &&
                       x.FacilityCode == facilityCode &&
                       propertyIdList.Contains(x.PropertyId) &&
                       startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate
                   select new CalculationValue
                   {
                       DateTime = x.CreatedDateTime,
                       Value = x.CurrentValue
                   })
                    .GroupBy(x => x.DateTime).Select(y => new CalculationValue
                    {
                        DateTime = y.Key,
                        //Value = y.Sum(item => item.Value) * ratedPowerConsumption / 60
                        Value = y.Sum(item => item.Value) // 2016 07 11 hcLee
                    }).OrderBy(x => x.DateTime);

            var bemsNoticePriceDetail
                = from x in db.BemsNoticePriceDetail
                  where x.SiteId == siteId &&
                  x.FuelTypeId == fuelTypeId &&
                  x.ContractType == contractType
                  select x;
            
            // 관제점 기록의 시간값을 기준으로 비용을 곱한값
            var resultGroupByHour = query
                .AsEnumerable()
                .Select(x => new CalculationValue
                { 
                    DateTime = x.DateTime,
                    Value = x.Value * GetNoticePriceFromDateTime(bemsNoticePriceDetail, x.DateTime, fuelTypeId) // 2016 07 11 hcLee
                });

            return resultGroupByHour.AsQueryable();
        }

        // timeInterval 기준으로 Group by 한다
        private IQueryable<CalculationValue> GetGroupedRuntimeCostValue(IQueryable<CalculationValue> resultGroupByHour, TimeInterval timeInterval)
        {
            switch (timeInterval)
            {
                case TimeInterval.Year:
                    return from x in resultGroupByHour
                           group x by new { Year = x.DateTime.Year }
                               into g
                               select new CalculationValue
                               {
                                   DateTime = new DateTime(g.Key.Year, 1, 1),
                                   Value = g.Sum(x => x.Value)
                               };
                case TimeInterval.Month:
                    return from x in resultGroupByHour
                           group x by new { Year = x.DateTime.Year, Month = x.DateTime.Month }
                               into g
                               select new CalculationValue
                               {
                                   DateTime = new DateTime(g.Key.Year, g.Key.Month, 1),
                                   Value = g.Sum(x => x.Value)
                               }; 
                case TimeInterval.Day:
                    return from x in resultGroupByHour
                           group x by new { Year = x.DateTime.Year, Month = x.DateTime.Month, Day = x.DateTime.Day }
                               into g
                               select new CalculationValue
                               {
                                   DateTime = new DateTime(g.Key.Year, g.Key.Month, g.Key.Day),
                                   Value = g.Sum(x => x.Value)
                               };
                case TimeInterval.Hour:
                    return resultGroupByHour;
                default:
                    return null;
            }
        }

        // 해당 dateTime보다 작은 Max 값을 하나 가져와서 시간 / 월에 해당하는 가격을 리턴
        private double GetNoticePriceFromDateTime(IQueryable<BemsNoticePriceDetail> bemsNoticePriceDetail, DateTime datetime, short fuelTypeId) // hcLee 2016 07 11
        {
            int hour = 0;
            if (fuelTypeId == 1)
            {
                hour = datetime.Hour;
            }
            BemsNoticePriceDetail noticePrice
                = (from x in bemsNoticePriceDetail
                   where x.DataId == hour
                  && x.ApplyDate <= datetime
                  orderby x.ApplyDate descending
                  select x).First();
            if (noticePrice == null) return 0;
            String columnNameFromMonth = String.Format("P{0:D2}", datetime.Month);            
            Nullable<Double> price = (Nullable<Double>)noticePrice.GetType().GetProperty(columnNameFromMonth).GetValue(noticePrice, null);
            return price == null ? 0 : (double)price;
        }

        // hcLee 2016 05 25
        [ActionName("FloorPointValue")]
        public List<double> GetBemsMonitoringPointHistoryFloorPointValue()
        //public List<CalculationValue[]> GetBemsMonitoringPointHistoryZoneTempHumi()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            //string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            //string uriStartDate = uriQuery.Get("StartDate");
            //string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId = -1; int floorId = -1;
            //DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false || 
                int.TryParse(uriQuery.Get("FloorId"), out floorId) == false )
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2}", siteId, buildingId, floorId));
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToListInLocation_FloorTempHumi(list, siteId, buildingId, floorId);

            List<double> listValue = new List<double>();
            //List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                foreach (var point in list)
                {
                    IEnumerable<BemsMonitoringPointHistory15min> lastData = (from data in db.BemsMonitoringPointHistory15min
                                                                             where data.SiteId == siteId && data.FacilityCode == point.FacilityCode && data.PropertyId == point.PropertyId
                                                                             orderby data.CreatedDateTime descending select data).Take(1);
                    if (lastData == null || lastData.Count() == 0)
                    {
                        //instance.cd = string.Format("{0:D10}", 1);
                        listValue.Add(-9999); // 데이터가 없는 경우 처리
                    }
                    else
                    {
                        BemsMonitoringPointHistory15min current = lastData.First();
                        listValue.Add(current.CurrentValue);
                    }
                }
                //return values;
                return listValue;
            }
            catch (Exception)
            {
                throw;
            }
        }

        // kgpark 2019 06 26
        [ActionName("FloorEachPointValue")]
        public List<double> GetBemsMonitoringPointHistoryFloorEachPointValue()
        //public List<CalculationValue[]> GetBemsMonitoringPointHistoryZoneTempHumi()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            //string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            //string uriStartDate = uriQuery.Get("StartDate");
            //string uriEndDate = uriQuery.Get("EndDate");

            int siteId; int floorId = -1;
            //DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("FloorId"), out floorId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1}", siteId, floorId));
            }


            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddEachPointToListInLocation_FloorTempHumi(list, siteId, floorId);

            List<double> listValue = new List<double>();
            //List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                foreach (var point in list)
                {
                    IEnumerable<BemsMonitoringPointHistory15min> lastData = (from data in db.BemsMonitoringPointHistory15min
                                                                             where data.SiteId == siteId && data.FacilityCode == point.FacilityCode && data.PropertyId == point.PropertyId
                                                                             orderby data.CreatedDateTime descending
                                                                             select data).Take(1);
                    if (lastData == null || lastData.Count() == 0)
                    {
                        //instance.cd = string.Format("{0:D10}", 1);
                        listValue.Add(-9999); // 데이터가 없는 경우 처리
                    }
                    else
                    {
                        BemsMonitoringPointHistory15min current = lastData.First();
                        listValue.Add(current.CurrentValue);
                    }
                }
                //return values;
                return listValue;
            }
            catch (Exception)
            {
                throw;
            }
        }

        [ActionName("RuntimeREFRIGERATOR")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryRumtimeREFRIGERATOR()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId = -1; int fuelTypeId = -1;
            int floorId, zoneId, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, buildingId, uriTimeIntervalType, uriStartDate, uriEndDate, fuelTypeId));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_Runtime_REFRIGERATOR(list, siteId); // 냉동기 가동시간

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
        }

        [ActionName("RuntimeBOILER")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryRumtimeBOILER()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId = -1; int fuelTypeId = -1;
            int floorId, zoneId, timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, buildingId, uriTimeIntervalType, uriStartDate, uriEndDate, fuelTypeId));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_Runtime_BOILER(list, siteId); // 보일러 가동시간

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
        }

        [ActionName("MonthMoney")]
        //public CalculationValue[] GetBemsMonitoringPointHistoryZoneTempHumi()
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryMonthMoney()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");
            string uriType = uriQuery.Get("Type"); // 10 전기 11 수도 12 가스

            int siteId;
            int timeInterval = -1; int nType = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                //int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriType, out nType) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4}",
                    siteId, uriTimeIntervalType, uriStartDate, uriEndDate, uriType));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var MM = from x in db.FmsBudgetDetailExecution
                         where x.SiteId == siteId && x.BudgetClassId == nType && (x.Year >= startDate.Year || x.Month >= startDate.Month) &&
                                (x.Year <= endDate.Year || x.Month <= endDate.Month)
                        select x;

                var values = CreateCalculationValues(startDate, endDate, timeIntervalType); // 위치 안으로 이동 2015 08 04 hcLee
                foreach (var point in MM) 
                {
                    CalculationValue v = null;

                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (point.Year == v.DateTime.Year && point.Month == v.DateTime.Month)
                        {
                            //v.Value += p.Value;
                            v.Value = point.MonthlyExecution;
                            //p = null;
                            //index++;
                            listCalc.Add(values);
                            break;
                            //if (pointValues.Length <= index) break;
                        }
                    }
                }
                //return values;
            }
            catch (Exception)
            {
                throw;
            }
            return listCalc;
        }

        [ActionName("CurrentValueFrom15min")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryCurrentValue()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            //string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            //string uriStartDate = uriQuery.Get("StartDate");
            //string uriEndDate = uriQuery.Get("EndDate");
            int siteId;
            int ValueType = -1;
            //DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("ValueType"), out ValueType) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1}", siteId, ValueType));
                //return listCalc;
            }
            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_ControlPoint(list, siteId, ValueType); // valueType이 특정인 포인트들만 (설정제어용)

            try
            {
                //var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
               //int v = 0;
                foreach (var point in list)
                {
                    CalculationValue[] values = new CalculationValue[2];

                    IEnumerable<BemsMonitoringPointHistory15min> lastData = (from data in db.BemsMonitoringPointHistory15min
                                                                             where data.SiteId == siteId && data.FacilityCode == point.FacilityCode && data.PropertyId == point.PropertyId
                                                                             orderby data.CreatedDateTime descending select data).Take(1);
                    values[0] = new CalculationValue
                    {
                        DateTime = new DateTime(),
                        Value = -9999
                    };

                    if (lastData == null || lastData.Count() == 0)
                    {
                        //instance.cd = string.Format("{0:D10}", 1);
                    }
                    else
                    {
                        BemsMonitoringPointHistory15min current = lastData.First();
                        values[0].Value = current.CurrentValue;
                    }

                    IEnumerable<BemsControlPointHistory> lastData2 = (from data in db.BemsControlPointHistory
                                                                      where data.SiteId == siteId && data.FacilityCode == point.FacilityCode && data.PropertyId == point.PropertyId
                                                                      orderby data.CreateDateTime descending select data).Take(1);
                    values[1] = new CalculationValue
                    {
                        DateTime = new DateTime(),
                        Value = -9999
                    };

                    if (lastData2 == null || lastData2.Count() == 0)
                    {
                        //instance.cd = string.Format("{0:D10}", 1);
                    }
                    else
                    {
                        BemsControlPointHistory current = lastData2.First();
                        values[1].Value = current.ControlValue;
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
            //return listCalc;
        }

        //**************** 2019.05.30. 가상설비, 일반설비 데이터 가져오기******************//
        [ActionName("VirtualNormalFacilityData")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryVirtualNormalCurrentValue()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriSiteId = uriQuery.Get("SiteId");
            string uriFacilityTypeId = uriQuery.Get("FacilityTypeId");
            string uriFacilityCode = uriQuery.Get("FacilityCode");
            string uriPropertyId = uriQuery.Get("PropertyId");
            string uriTimeInterval = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId = -1, facilityTypeId = -1, propertyId = -1, timeInterval = -1, facilityCode = -1;

            DateTime startDate, endDate;
            if (int.TryParse(uriSiteId, out siteId) == false ||
                int.TryParse(uriFacilityTypeId, out facilityTypeId) == false ||
                int.TryParse(uriPropertyId, out propertyId) == false ||
                int.TryParse(uriTimeInterval, out timeInterval) == false ||
                int.TryParse(uriFacilityCode, out facilityCode) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, facilityTypeId, propertyId, uriTimeInterval, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;


            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_ControlPoint2(list, siteId, propertyId, facilityTypeId, facilityCode); // 2019.05.30. 관제점 정보 확보

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
        }
        //**************** 2019.05.30. 가상설비, 일반설비 데이터 가져오기****************** kgpark


        //**************** 2020.05. 예측 데이터 가져오기****************** kgpark
        [ActionName("ForecastingDayAheadData")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryForecastingDayAheadValue()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriSiteId = uriQuery.Get("SiteId");
            string uriFacilityTypeId = uriQuery.Get("FacilityTypeId");
            string uriFacilityCode = uriQuery.Get("FacilityCode");
            string uriPropertyId = uriQuery.Get("PropertyId");
            string uriTimeInterval = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId = -1, facilityTypeId = -1, propertyId = -1, timeInterval = -1, facilityCode = -1;

            DateTime startDate, endDate;
            if (int.TryParse(uriSiteId, out siteId) == false ||
                int.TryParse(uriFacilityTypeId, out facilityTypeId) == false ||
                int.TryParse(uriPropertyId, out propertyId) == false ||
                int.TryParse(uriTimeInterval, out timeInterval) == false ||
                int.TryParse(uriFacilityCode, out facilityCode) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, facilityTypeId, propertyId, uriTimeInterval, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;


            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_ControlPoint2(list, siteId, propertyId, facilityTypeId, facilityCode); // 관제점 정보 확보

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    // 여기서 데이터 받아옴
                    var pointValues = pointHistoryValueManager.GetPointForecastingDayAheadValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
            //return listCalc;
        }
        
        [ActionName("ForecastingHourAheadData")]
        public List<CalculationValue[]> GetBemsMonitoringPointHistoryForecastingHourAheadValue()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriSiteId = uriQuery.Get("SiteId");
            string uriFacilityTypeId = uriQuery.Get("FacilityTypeId");
            string uriFacilityCode = uriQuery.Get("FacilityCode");
            string uriPropertyId = uriQuery.Get("PropertyId");
            string uriTimeInterval = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId = -1, facilityTypeId = -1, propertyId = -1, timeInterval = -1, facilityCode = -1;

            DateTime startDate, endDate;
            if (int.TryParse(uriSiteId, out siteId) == false ||
                int.TryParse(uriFacilityTypeId, out facilityTypeId) == false ||
                int.TryParse(uriPropertyId, out propertyId) == false ||
                int.TryParse(uriTimeInterval, out timeInterval) == false ||
                int.TryParse(uriFacilityCode, out facilityCode) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}",
                    siteId, facilityTypeId, propertyId, uriTimeInterval, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;


            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_ControlPoint2(list, siteId, propertyId, facilityTypeId, facilityCode); // 관제점 정보 확보

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    // 여기서 데이터 받아옴
                    var pointValues = pointHistoryValueManager.GetPointForecastingHourAheadValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
            //return listCalc;
        }
        //**************** 2020.05. 예측 데이터 가져오기****************** kgpark

        //**************** 2020.08. 축열조 시뮬레이터 관련 데이터 가져오기****************** kgpark
        [ActionName("IceThermalStorageSimulation")]
        public List<CalculationValue[]> GetIceThermalStorageSimulationValue()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriSiteId = uriQuery.Get("SiteId");
            string uriFacilityTypeId = uriQuery.Get("FacilityTypeId");
            string uriFacilityCode = uriQuery.Get("FacilityCode");
            string uriPropertyId = uriQuery.Get("PropertyId");
            string uriSimulationCase = uriQuery.Get("SimulationCase");
            string uriTimeInterval = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId = -1, facilityTypeId = -1, propertyId = -1, timeInterval = -1, facilityCode = -1, simulationCase = -1;

            DateTime startDate, endDate;
            if (int.TryParse(uriSiteId, out siteId) == false ||
                int.TryParse(uriFacilityTypeId, out facilityTypeId) == false ||
                int.TryParse(uriPropertyId, out propertyId) == false ||
                int.TryParse(uriSimulationCase, out simulationCase) == false ||
                int.TryParse(uriTimeInterval, out timeInterval) == false ||
                int.TryParse(uriFacilityCode, out facilityCode) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5},{6}",
                    siteId, facilityTypeId, propertyId, uriTimeInterval, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            AddPointToList_ControlPoint2(list, siteId, propertyId, facilityTypeId, facilityCode); // 관제점 정보 확보

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            try
            {
                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    // 여기서 데이터 받아옴
                    var pointValues = pointHistoryValueManager.GetPointIceThermalStorageSimulationValues(
                        siteId, point.FacilityCode, point.PropertyId, simulationCase,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                    listCalc.Add(values);
                }
                return listCalc;
            }
            catch (Exception)
            {
                throw;
            }
            //return listCalc;
        }
        //**************** 2020.08. 축열조 시뮬레이터 관련 데이터 가져오기****************** kgpark

        [ResponseType(typeof(void))]
        [ActionName("ControlPoint")]
        public IHttpActionResult PostControlPoint()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriSiteId = uriQuery.Get("SiteId");
            string uriFacilityTypeId = uriQuery.Get("FacilityTypeId");
            string uriFacilityCode = uriQuery.Get("FacilityCode");
            string uriPropertyId = uriQuery.Get("PropertyId");
            string uriControlValue = uriQuery.Get("ControlValue");

            int siteId = -1, facilityTypeId = -1, propertyId = -1, facilityCode = -1;
            double controlValue = 0;

            if (int.TryParse(uriSiteId, out siteId) == false ||
                int.TryParse(uriFacilityTypeId, out facilityTypeId) == false ||
                int.TryParse(uriPropertyId, out propertyId) == false ||
                int.TryParse(uriFacilityCode, out facilityCode) == false ||
                double.TryParse(uriControlValue, out controlValue) == false)
            {
                throw new Exception(string.Format("Not Found FFFF Parameters: {0},{1},{2},{3},{4} ", uriSiteId, uriFacilityTypeId, facilityCode, uriPropertyId, uriControlValue));
            }

            DateTime currentTime = DateTime.Now;
            using (var transaction = new TransactionScope())
            {
                try
                {
                    {
                        var control = new BemsControlPointHistory
                        {
                            SiteId = siteId,
                            FacilityTypeId = facilityTypeId, // 2015 08 05 DB 문제로 일단 99로 테스트함, 정상코드는 아래줄이다.
                            FacilityCode = facilityCode,
                            PropertyId = propertyId,    // ???? hcLee
                            CreateDateTime = currentTime,
                            ControlValue = controlValue,
                            WriteServiceName = null,
                            ActionDateTime = null
                        };
                        db.BemsControlPointHistory.Add(control);
                        db.SaveChanges();
                    }

                }
                catch (Exception e)
                {
                    Trace.WriteLine(e.Message);
                    //throw e;
                    throw;
                }
                transaction.Complete();
            }

            return StatusCode(HttpStatusCode.NoContent);
        }

        [ActionName("LCCViewPreSum")]
        public List<double> GetBemsMonitoringPointHistoryLCCViewPreSum()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");
            //string uriType = uriQuery.Get("Type"); // 10 전기 11 수도 12 가스

            int siteId;
            int timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3}", siteId, uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            List<CalculationValue[]> listCalc = new List<CalculationValue[]>();

            List<FmsBudgetCodeClass> listCode = new List<FmsBudgetCodeClass>();
            var dd = from x in db.FmsBudgetCodeClass where x.Depth == 0 select x;
            listCode = dd.ToList();

            List<double> listTotalSum = new List<double>();
            foreach (FmsBudgetCodeClass code in listCode)
            {
                var MM = from x in db.FmsBudgetDetailExecution
                         where x.SiteId == siteId && x.Year >= 1000 && x.Month >= 0 && // 최초부터
                                x.Year < startDate.Year || (x.Year == startDate.Year && x.Month < startDate.Month)
                         from c in db.FmsBudgetCodeClass
                         where c.BudgetSeq.Substring(0, 2) == code.BudgetSeq && x.BudgetClassId == c.BudgetClassId
                         select x;

                double sum = new double();
                foreach (var point in MM)
                {
                    sum += point.MonthlyExecution;
                }
                listTotalSum.Add(sum);
            }

            return listTotalSum;
        }

        [ActionName("LCCView")]
        public List<CalculationValueBudget[]> GetBemsMonitoringPointHistoryLCCView()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");
            //string uriType = uriQuery.Get("Type"); // 10 전기 11 수도 12 가스

            int siteId;
            int timeInterval = -1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3}", siteId, uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            List<CalculationValueBudget[]> listCalc = new List<CalculationValueBudget[]>();

            List<FmsBudgetCodeClass> listCode = new List<FmsBudgetCodeClass>();
            var dd = from x in db.FmsBudgetCodeClass where x.Depth == 0 select x;
            listCode = dd.ToList();

            foreach (FmsBudgetCodeClass code in listCode)
            {
                var MM = from x in db.FmsBudgetDetailExecution
                         where x.SiteId == siteId && x.Year >= startDate.Year && x.Month >= startDate.Month &&
                                x.Year < endDate.Year || (x.Year == endDate.Year && x.Month <= endDate.Month)
                         from c in db.FmsBudgetCodeClass
                         where c.BudgetSeq.Substring(0, 2) == code.BudgetSeq && x.BudgetClassId == c.BudgetClassId
                         select x;


                var values = CreateCalculationValuesBudget(startDate, endDate, timeIntervalType); // 위치 안으로 이동 2015 08 04 hcLee
                foreach (var point in MM)
                {
                    CalculationValueBudget v = null;

                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (point.Year == v.DateTime.Year && point.Month == v.DateTime.Month)
                        {
                            v.Value += point.MonthlyExecution;
                            v.Value2 += point.MonthlyBudget;
                            break;
                        }
                    }
                }
                listCalc.Add(values);
            }
            return listCalc;
        }

        [ActionName("FmsHouseStock")]
        public List<FmsHouseStockEx> GetBemsMonitoringFmsHouseStock()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriBusinessId = uriQuery.Get("BusinessId");

            int siteId;
            int BusinessId = -1;
            //DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriBusinessId, out BusinessId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1}", siteId, uriBusinessId));
            }

            List<FmsMaterialWarehouse> listHouse = new List<FmsMaterialWarehouse>();
            var hh = from h in db.FmsMaterialWarehouse where h.SiteId == siteId select h;
            listHouse = hh.ToList();

            List<FmsHouseStockEx> listEx = new List<FmsHouseStockEx>();

            foreach (FmsMaterialWarehouse h in listHouse)
            {
                var query = from data in db.FmsMaterialStored
                //var query = from data in db.FmsMaterialEx
                            //where (data.SiteId == siteId && data.WarehouseId == h.WarehouseId && M.MaterialId == data.MaterialId)
                            where (data.SiteId == siteId && data.WarehouseId == h.WarehouseId)
                            from M in db.FmsMaterial
                            where M.SiteId == siteId && M.MaterialId == data.MaterialId
                            group data by new { data.MaterialId, M.MaterialCode, M.Name } into g
                            select new
                            {
                                HouseName = h.Name,
                                MaterialId = g.Key.MaterialId,
                                StockCnt = g.Sum(data => data.RemainStoredCount),
                                MName = g.Key.Name,
                                MaterialCode = g.Key.MaterialCode
                            };
                                                                                     
                foreach (var v in query)
                {
                    FmsHouseStockEx ex = new FmsHouseStockEx();
                    ex.MaterialId = v.MaterialId;
                    ex.MaterialCode= v.MaterialCode;
                    ex.MName = v.MName;
                    ex.HouseName = v.HouseName;
                    ex.StockCnt = v.StockCnt;
                    listEx.Add(ex);
                }                                                                                       
            }
              
            return listEx;
/*
            List<double> listTotalSum = new List<double>();
            foreach (FmsBudgetCodeClass code in listCode)
            {
                var MM = from x in db.FmsBudgetDetailExecution
                         where x.SiteId == siteId && x.Year >= 1000 && x.Month >= 0 && // 최초부터
                                x.Year < startDate.Year || (x.Year == startDate.Year && x.Month < startDate.Month)
                         from c in db.FmsBudgetCodeClass
                         where c.BudgetSeq.Substring(0, 2) == code.BudgetSeq && x.BudgetClassId == c.BudgetClassId
                         select x;

                double sum = new double();
                foreach (var point in MM)
                {
                    sum += point.MonthlyExecution;
                }
                listTotalSum.Add(sum);
            }

            return listTotalSum;*/
        }


        [ActionName("GetCenterSiteData")]
        public List<CenterSiteData> PostGetCenterSiteData(GetCenterSiteData_Param param)
        {
            int timeIntervalType = param.TimeIntervalType;
            DateTime startDate = param.startDate, endDate = param.endDate;

            DateTime currentTime = DateTime.Now;
            DateTime todayStart = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 0, 0, 0);

            List<CenterSiteData> list = new List<CenterSiteData>();
            IEnumerable<CmSite> sites = from data in db.CmSite where data.SiteId > 0 select data;

            BemsFormulaController FC = new BemsFormulaController();
            //1.100.1.1 3
            foreach (CmSite s in sites)
            {
                CenterSiteData cd = new CenterSiteData();
                cd.siteid = s.SiteId;
                cd.name = s.Name;
                //List<CalculationValue> listC = new List<CalculationValue>();
                //listC.Add(new CalculationValue());
                cd.e_value_list = FC.GetBemsFormulaReal(s.SiteId, 100, 1, 1, todayStart, currentTime, 2); // hour
                cd.g_value_list = FC.GetBemsFormulaReal(s.SiteId, 101, 2, 1, todayStart, currentTime, 2); // hour

                List<CalculationResult> listEYear = FC.GetBemsFormulaReal(s.SiteId, 100, 1, 1, startDate, endDate, timeIntervalType);
                cd.elec_current = (listEYear.Count() <= 0) ? 0 : listEYear[0].Value;

                List<CalculationResult> listGYear = FC.GetBemsFormulaReal(s.SiteId, 101, 2, 1, startDate, endDate, timeIntervalType);
                cd.gas_current = (listGYear.Count() <= 0) ? 0 : listGYear[0].Value;

                //cd.kcal_target = 300;
                var G = from x in db.BemsEnergyDaily
                        where (x.SiteId == s.SiteId && x.FuelTypeId == 1 && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                        group x by new { x.SiteId } into g
                        select new { P = g.Sum(x => x.Goal) };
                //listPrediction.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0);
                cd.elec_target = G.Count() > 0 ? (double)G.FirstOrDefault().P : 0;

                G = from x in db.BemsEnergyDaily
                    where (x.SiteId == s.SiteId && x.FuelTypeId == 2 && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                    group x by new { x.SiteId } into g
                    select new { P = g.Sum(x => x.Goal) };
                cd.gas_target = G.Count() > 0 ? (double)G.FirstOrDefault().P : 0;

                list.Add(cd);

            }

            return list;
        }


        // 차후를 생각해      BuildingId와 FuelType, 날짜를 받지만 현재 의미는 없다 hcLee 2016 03 18
        [ActionName("GetPrediction")]
        public List<double> PostGetPrediction(GetPrediction_Param param)
        {
/*            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            //string uriBuildingId = uriQuery.Get("BuildingId");
            string uriFuelType = uriQuery.Get("FuelType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");
            //string uriType = uriQuery.Get("Type"); // 10 전기 11 수도 12 가스

            int siteId;
            int fueltype = -1;  int buildingId = 0;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriFuelType, out fueltype) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5}", siteId, buildingId, uriFuelType, uriStartDate, uriEndDate));
            }*/
            //int timeIntervalType = (TimeInterval)timeInterval;
            //List<CalculationValue[]> listCalc = new List<CalculationValue[]>();
            List<double> listPrediction = new List<double>();
            DateTime startDate, endDate;
            
            int siteId = param.SiteId;
            DateTime currentTime = DateTime.Now;
            startDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 0, 0, 0);
            endDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 23, 59, 59);

            for (int i = 0; i < 3; i++)
            {
                // 오늘의 전기 가스 수도 TOE
                var G = from x in db.BemsEnergyDaily
                        where (x.SiteId == siteId && x.FuelTypeId == 1 && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                        group x by new { x.SiteId } into g
                        select new { P = g.Sum(x => x.Goal) };
                listPrediction.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0);

                G = from x in db.BemsEnergyDaily
                    where (x.SiteId == siteId && x.FuelTypeId == 2 && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                    group x by new { x.SiteId } into g
                    select new { P = g.Sum(x => x.Goal) };
                listPrediction.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0);

                G = from x in db.BemsEnergyDaily
                    where (x.SiteId == siteId && x.FuelTypeId == 3 && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                    group x by new { x.SiteId } into g
                    select new { P = g.Sum(x => x.Goal) };
                listPrediction.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0);
                                         /*
                G = from x in db.BemsEnergyGoalDaily
                    where (x.SiteId == siteId && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                    group x by new { x.SiteId } into g select new { P = g.Sum(x => x.Goal) };
                listPrediction.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0); */
                //Why(listPrediction, siteId, startDate, endDate); 2016 07 15 테이블 삭제

                if (i == 0) // 두번쨰 루프시작전 이번달
                {
                    startDate = new DateTime(currentTime.Year, currentTime.Month, 1, 0, 0, 0);
                    endDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 23, 59, 59);
                }
                else if (i == 1) // 세번쨰 루프시작전 금년
                {
                    startDate = new DateTime(currentTime.Year, 1, 1, 0, 0, 0);
                    endDate = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 23, 59, 59);
                }
            }

            return listPrediction;  // 4 x 3  12개의 값          -> 9
        }
        

        /*                   {}
        private void Why(List<double> list, int siteId, DateTime startDate, DateTime endDate)
        {
            //var G = from x in db.BemsEnergyGoalDaily 2016 07 15
            var G = from x in db.BemsEnergyDaily
                where (x.SiteId == siteId && x.CreatedDate >= startDate && x.CreatedDate <= endDate)
                group x by new { x.SiteId } into g select new { P = g.Sum(x => x.Goal) };
            list.Add(G.Count() > 0 ? (double)G.FirstOrDefault().P : 0);

        }   */

        private void NextTimeFromTimeInterval( ref DateTime datetime, TimeInterval timeIntervalType )
        {
            switch( timeIntervalType )
            {
                case TimeInterval.QuarterMin:
                    datetime = datetime.AddMinutes( 15 );
                    break;
                case TimeInterval.Hour:
                    datetime = datetime.AddHours( 1 );
                    break;
                case TimeInterval.Day:
                    datetime = datetime.AddDays( 1 );
                    break;
                case TimeInterval.Month:
                    datetime = datetime.AddMonths( 1 );
                    break;
                default: // TimeInterval.Year:
                    datetime = datetime.AddYears( 1 );
                    break;
            }
        }

        private int GetCountInTimeRange( DateTime startDate , DateTime endDate , TimeInterval timeIntervalType )
        {
            TimeSpan ts = endDate - startDate;
            switch( timeIntervalType )
            {
                case TimeInterval.QuarterMin:
                    return (int)ts.TotalMinutes / 15 + 1;
                case TimeInterval.Hour:
                    return (int)ts.TotalHours + 1;
                case TimeInterval.Day:
                    return (int)ts.TotalDays + 1;
                case TimeInterval.Month:
                    {
                        int count = 0;
                        DateTime date = startDate;
                        //while (date.Year <= endDate.Year && date.Month <= endDate.Month) // hcLee 헐~
                        while (date <= endDate)      // hcLee
                        {
                            count++;
                            date = date.AddMonths( 1 );
                        }
                        return count;
                    }
                default: // TimeInterval.Year:
                    {
                        int count = 0;
                        DateTime date = startDate;
                        while( date.Year <= endDate.Year)
                        {
                            count++;
                            date = date.AddYears( 1 );
                        }
                        return count;
                    }
            }
            
        }

        private CalculationValue[] CreateCalculationValues( DateTime startDate , DateTime endDate , TimeInterval timeIntervalType )
        {
            DateTime datetime = startDate;
            int count = GetCountInTimeRange( startDate , endDate , timeIntervalType );
            CalculationValue[] values = new CalculationValue[count];

            for( var i = 0 ; i < values.Length ; i++ )
            {
                values[i] = new CalculationValue
                {
                    DateTime = datetime ,
                    Value = 0
                };
                NextTimeFromTimeInterval( ref datetime , timeIntervalType );
            }
            return values;
        }

        private CalculationValueBudget[] CreateCalculationValuesBudget(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType)
        {
            DateTime datetime = startDate;
            int count = GetCountInTimeRange(startDate, endDate, timeIntervalType);
            CalculationValueBudget[] values = new CalculationValueBudget[count];

            for (var i = 0; i < values.Length; i++)
            {
                values[i] = new CalculationValueBudget
                {
                    DateTime = datetime,
                    Value = 0,
                    Value2 = 0
                };
                NextTimeFromTimeInterval(ref datetime, timeIntervalType);
            }
            return values;
        }

        private CalculationValueSType[] CreateCalculationValuesSType(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType)
        {
            DateTime datetime = startDate;
            int count = GetCountInTimeRange(startDate, endDate, timeIntervalType);
            
            var query = from x in db.BemsServiceType where x.ServiceTypeId < 100 && x.ServiceTypeId > 0 select x;
            //foreach (CmBuilding b in query)
            CalculationValueSType[] values = new CalculationValueSType[count * query.Count()];
            //CalculationValueSType[] values = new CalculationValueSType[count][query.Count()];

            int j = 0;
            for (var i = 0; i < count; i++)
            {
                foreach (BemsServiceType S in query)
                {
                    values[j] = new CalculationValueSType
                    {
                        DateTime = datetime,
                        Value = 0,
                        ServiceType = S.ServiceTypeId
                    };
                    j++;
                }
                NextTimeFromTimeInterval(ref datetime, timeIntervalType);
                //j += query.Count();
            }
            return values;
        }

        private void AddPointToListInLocation( List<MonitoringPoint> list ,
            int siteId , int fuelTypeId , int buildingId , int? floorId , int? zoneId )
        {
            {
                bool bEnd = false;
                IQueryable<MonitoringPoint> query;
                // floorId 나 zoneId 가 null를 가지고 있어도, 비교시에는 null로 비교하지 않는다. 
                // 그래서 강제적으로 조건에 따라 null를 비교하도록 수정
                if( floorId == null && zoneId == null ) // 건물처리
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId &&
                                  x.BuildingId == buildingId && x.FloorId == null && x.ZoneId == null
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case1"));
                }
                else if (floorId != null && zoneId == null)        // 층처리           층이고 zone이 null인 즉 층전체포인트가 있으면
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId &&
                                  x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == null
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                }
                else  // 구역처리
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId &&
                                  x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == zoneId
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId ,
                                FacilityCode = x.FacilityCode ,
                                PropertyId = x.PropertyId ,
                            };
                    bEnd = true;
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if( query.Any() )
                {
                    foreach( var data in query )
                    {
                        list.Add( data );
                    }
                    return; // 있으면 끝
                }
                if (bEnd) return;
            }
            {
                if( floorId == null ) // 
                {
                    var query = from x in db.CmFloor
                                where x.SiteId == siteId && x.BuildingId == buildingId 
                                select x.FloorId;
                    if (query.Any())
                    {
                        foreach (var floor in query)
                        {
                            AddPointToListInLocation(list, siteId, fuelTypeId, buildingId, floor, null);
                        }
                    }
                }
                //else if( zoneId == null )
                //if( zoneId == null )
                if (zoneId == null)
                //else
                {
                    var query = from x in db.CmZone
                                where x.SiteId == siteId && x.BuildingId == buildingId && x.FloorId == floorId 
                                select x.ZoneId;
                    if (query.Any())
                    {
                        foreach (var zone in query)
                        {
                            AddPointToListInLocation(list, siteId, fuelTypeId, buildingId, floorId, zone);
                        }
                    }
                }
            }
        }

        private void AddPointToListInLocationSType_New(List<MonitoringPointSType> list, int siteId, int buildingId, int fuelTypeId)
        {
            var q = from x in db.BemsServiceType
                    where x.ServiceTypeId > 0 && x.ServiceTypeId < 100
                    select x;

            IQueryable<MonitoringPointSType> query;
            foreach (var stype in q)
            {
                //AddPointToListInLocation(list, siteId, fuelTypeId, buildingId, floorId, zone);
                query = from x in db.BemsMonitoringPoint
                        where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId == stype.ServiceTypeId &&
                              x.BuildingId == buildingId && x.FloorId == null
                        select new MonitoringPointSType
                        {
                            SiteId = x.SiteId,
                            FacilityCode = x.FacilityCode,
                            PropertyId = x.PropertyId,
                            ServiceTypeId = (int)x.ServiceTypeId,
                        };
                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                }
                else // 빌딩만 매핑이 없으면 각 층
                {
                    IQueryable<CmFloor> qF;
                    qF = from x in db.CmFloor
                         where x.SiteId == siteId && x.BuildingId == buildingId
                         select x;
                    foreach (var floor in qF)
                    {
                        query = from x in db.BemsMonitoringPoint
                                where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId == stype.ServiceTypeId &&
                                      x.BuildingId == buildingId && x.FloorId == floor.FloorId && x.ZoneId == null
                                select new MonitoringPointSType
                                {
                                    SiteId = x.SiteId,
                                    FacilityCode = x.FacilityCode,
                                    PropertyId = x.PropertyId,
                                    ServiceTypeId = (int)x.ServiceTypeId,
                                };
                        //n = query.Count();
                        if (query.Any())
                        {
                            foreach (var data in query)
                            {
                                list.Add(data);
                            }
                        }
                        else
                        {
                            query = from x in db.BemsMonitoringPoint
                                    where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId == stype.ServiceTypeId &&
                                          x.BuildingId == buildingId && x.FloorId == floor.FloorId && x.ZoneId != null
                                    select new MonitoringPointSType
                                    {
                                        SiteId = x.SiteId,
                                        FacilityCode = x.FacilityCode,
                                        PropertyId = x.PropertyId,
                                        ServiceTypeId = (int)x.ServiceTypeId,
                                    };
                            if (query.Any())
                            {
                                foreach (var data in query)
                                {
                                    list.Add(data);
                                }
                            }

                        }
                    }
                }
            }
        }
        private void AddPointToListInLocationSType_New2(List<MonitoringPointSType> list, int siteId, int buildingId)
        {
            var q = from x in db.BemsServiceType
                        where x.ServiceTypeId > 0 && x.ServiceTypeId < 100 select x;

            IQueryable<MonitoringPointSType> query;
            foreach (var stype in q)
            {
                query = from x in db.BemsMonitoringPoint
                        where x.SiteId == siteId && x.ServiceTypeId == stype.ServiceTypeId &&
                              x.FuelTypeId > 0 && // 2017 02 17 hcLee 방어코드 추가, 보라매현장 DB입력 오류 (서비스타입은 있는데 Fuel이 0인 포인트 존재) 회피코드           
                              x.BuildingId == buildingId && x.FloorId == null 
                        select new MonitoringPointSType
                        {
                            SiteId = x.SiteId,
                            FacilityCode = x.FacilityCode,
                            PropertyId = x.PropertyId,
                            ServiceTypeId = (int)x.ServiceTypeId,
                            FuelTypeId = (int)x.FuelTypeId,
                        };
                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                }
                else // 빌딩만 매핑이 없으면 각 층
                {
                    IQueryable<CmFloor> qF;
                    qF = from x in db.CmFloor
                                where x.SiteId == siteId && x.BuildingId == buildingId select x;
                    foreach (var floor in qF)
                    {
                        query = from x in db.BemsMonitoringPoint
                                //where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId == stype.ServiceTypeId &&
                                where x.SiteId == siteId && x.ServiceTypeId == stype.ServiceTypeId &&
                                      x.BuildingId == buildingId && x.FloorId == floor.FloorId && x.ZoneId == null
                                select new MonitoringPointSType
                                {
                                    SiteId = x.SiteId,
                                    FacilityCode = x.FacilityCode,
                                    PropertyId = x.PropertyId,
                                    ServiceTypeId = (int)x.ServiceTypeId,
                                    FuelTypeId = (int)x.FuelTypeId,
                                };
                        //n = query.Count();
                        if (query.Any())
                        {
                            foreach (var data in query)
                            {
                                list.Add(data);
                            }
                        }
                        else
                        {
                            query = from x in db.BemsMonitoringPoint
                                    //where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId == stype.ServiceTypeId &&
                                    where x.SiteId == siteId && x.ServiceTypeId == stype.ServiceTypeId &&
                                          x.BuildingId == buildingId && x.FloorId == floor.FloorId && x.ZoneId != null
                                    select new MonitoringPointSType
                                    {
                                        SiteId = x.SiteId,
                                        FacilityCode = x.FacilityCode,
                                        PropertyId = x.PropertyId,
                                        ServiceTypeId = (int)x.ServiceTypeId,
                                        FuelTypeId = (int)x.FuelTypeId,
                                    };
                            if (query.Any())
                            {
                                foreach (var data in query)
                                {
                                    list.Add(data);
                                }
                            }

                        }
                    }
                }
                
            }

        }

        private void AddPointToListInLocationSType(List<MonitoringPointSType> list,
            int siteId, int fuelTypeId, int buildingId, int? floorId, int? zoneId)
        {
            {
                IQueryable<MonitoringPointSType> query;
                // floorId 나 zoneId 가 null를 가지고 있어도, 비교시에는 null로 비교하지 않는다. 
                // 그래서 강제적으로 조건에 따라 null를 비교하도록 수정
                if (floorId != null && zoneId == null)        // 층처리           층이고 zone이 null인 즉 층전체포인트가 있으면
                {
                    query = from x in db.BemsMonitoringPoint
                            //where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 &&  2015 08 04 추가 ServiceType에 온도와 습도가 포함되면서 아래로 변경함.
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 && x.ServiceTypeId < 100 &&
                                  x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == null
                            select new MonitoringPointSType
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                                ServiceTypeId = (int)x.ServiceTypeId,
                            };
                    //throw new Exception(string.Format("case1"));
                }
                else if (floorId == null && zoneId == null) // 건물처리
                {
                    query = from x in db.BemsMonitoringPoint
                            //where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 &&
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 && x.ServiceTypeId < 100 &&
                                  x.BuildingId == buildingId && x.FloorId == null && x.ZoneId == null
                            select new MonitoringPointSType
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                                ServiceTypeId = (int)x.ServiceTypeId,
                            };
                }
                else  // 구역처리
                {
                    query = from x in db.BemsMonitoringPoint
                            //where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 &&
                            where x.SiteId == siteId && x.FuelTypeId == fuelTypeId && x.ServiceTypeId != 0 && x.ServiceTypeId < 100 &&
                                  x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == zoneId
                            select new MonitoringPointSType
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                                ServiceTypeId = (int)x.ServiceTypeId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
            {
                if (floorId == null) // 
                {
                    var query = from x in db.CmFloor
                                where x.SiteId == siteId && x.BuildingId == buildingId 
                                select x.FloorId;

                    foreach (var floor in query)
                    {
                        AddPointToListInLocationSType(list, siteId, fuelTypeId, buildingId, floor, null);
                    }
                }
                //else if( zoneId == null )
                if (zoneId == null)
                //else
                {
                    var query = from x in db.CmZone
                                where x.SiteId == siteId && x.BuildingId == buildingId && x.FloorId == floorId
                                select x.ZoneId;

                    foreach (var zone in query)
                    {
                        AddPointToListInLocationSType(list, siteId, fuelTypeId, buildingId, floorId, zone);
                    }
                }
            }
        }

        //구역에 맵핑된 온도, 습도 포인트만 찾아낸다.                   // 한가지씩찾아서 평균으로 수정필요함
        private void AddPointToListInLocation_ZoneTempHumi(List<MonitoringPoint> list,
            int siteId, int buildingId, int? floorId, int? zoneId)
        {
            {
                IQueryable<MonitoringPoint> query;
                // floorId 나 zoneId 가 null를 가지고 있어도, 비교시에는 null로 비교하지 않는다. 
                // 그래서 강제적으로 조건에 따라 null를 비교하도록 수정
                //   x.FacilityTypeId 91, 92로 가려야 한다. 2015 08 03 hcLee    -> x
                {
                    query = from x in db.BemsMonitoringPoint
                            //where x.SiteId == siteId && (x.PropertyId == 1000 ||x.PropertyId == 1001)  &&  2015 08 04 hcLee 서비스타입으로 변경함.
                            //where x.SiteId == siteId && (x.ServiceTypeId == 100 || x.ServiceTypeId == 110) && // 2016 04 18 co2농도도 추가
                            where x.SiteId == siteId && (x.ServiceTypeId == 100 || x.ServiceTypeId == 110 || x.ServiceTypeId == 130) &&
                                  x.BuildingId == buildingId && x.FloorId == floorId && x.ZoneId == zoneId
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        //2016 05 25 hcLee
        //층에  맵핑된 온도(100), 습도(110), CO2(130), CO(140) 포인트만 찾아낸다. 평면도 그리는 화면 에너지현황/실내온습도 상태감시 화면에서 사용
        private void AddPointToListInLocation_FloorTempHumi(List<MonitoringPoint> list, int siteId, int buildingId, int? floorId)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.FacilityTypeId == 99 && (x.ServiceTypeId == 100 || x.ServiceTypeId == 110 || x.ServiceTypeId == 130 || x.ServiceTypeId == 140 || x.ServiceTypeId == 150 || x.ServiceTypeId == 160) &&
                                  x.BuildingId == buildingId && x.FloorId == floorId orderby x.Name
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        //2019 06 26 kgpark
        //층에  맵핑된 온도(100), 습도(110), CO2(130), CO(140), 미세먼지(150), O3(160) 포인트만 찾아낸다. 평면도 그리는 화면 에너지현황/실내온습도 상태감시 화면에서 사용
        private void AddEachPointToListInLocation_FloorTempHumi(List<MonitoringPoint> list, int siteId, int? floorId)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsFloorStatus
                            where x.SiteId == siteId && x.FacilityTypeId == 99 && x.FloorId == floorId
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        private void AddPointToList_RunTime(List<MonitoringPoint> list, int siteId, int facilityCode)
        {
            {
                IQueryable<MonitoringPoint> query;
                // floorId 나 zoneId 가 null를 가지고 있어도, 비교시에는 null로 비교하지 않는다. 
                // 그래서 강제적으로 조건에 따라 null를 비교하도록 수정
                //   x.FacilityTypeId 91, 92로 가려야 한다. 2015 08 03 hcLee    -> x
                {
                    query = from x in db.BemsMonitoringPoint
                            //where x.SiteId == siteId && (x.PropertyId == 1000 ||x.PropertyId == 1001)  &&  2015 08 04 hcLee 서비스타입으로 변경함.
                            where x.SiteId == siteId && x.ServiceTypeId == 120 && x.FacilityCode == facilityCode
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        private void AddPointToList_Runtime_REFRIGERATOR(List<MonitoringPoint> list, int siteId)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.FacilityTypeId == 2 && x.PropertyId == 17 
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        private void AddPointToList_Runtime_BOILER(List<MonitoringPoint> list, int siteId)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && ((x.FacilityTypeId == 8 && x.PropertyId == 9) || (x.FacilityTypeId == 14 && x.PropertyId == 7))
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }

        private void AddPointToList_ControlPoint(List<MonitoringPoint> list, int siteId, int ValueType)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsMonitoringPoint
                            //2016 01 18
                            //where x.SiteId == siteId && x.ValueType == ValueType
                            where x.SiteId == siteId && (x.ValueType == 1 || x.ValueType == 3)
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }
        
        //2020.05.****************
        private void AddPointToList_ControlPoint2(List<MonitoringPoint> list, int siteId, int propertyId, int facilityTypeId, int facilitycode)
        {
            {
                IQueryable<MonitoringPoint> query;
                {
                    query = from x in db.BemsMonitoringPoint
                            where x.SiteId == siteId && x.PropertyId == propertyId && x.FacilityTypeId == facilityTypeId && x.FacilityCode == facilitycode
                            select new MonitoringPoint
                            {
                                SiteId = x.SiteId,
                                FacilityCode = x.FacilityCode,
                                PropertyId = x.PropertyId,
                            };
                    //throw new Exception(string.Format("case4"));
                }

                //int n = query.Count();
                if (query.Any())
                {
                    foreach (var data in query)
                    {
                        list.Add(data);
                    }
                    return; // 있으면 끝
                }
            }
        }
        //*******************2020.05.

 /*
        [ActionName("ServiceType")]
        public CalculationValue[] GetBemsMonitoringPointHistoryServiceType()
        {
            Uri uri = Request.RequestUri;
            var uriQuery = HttpUtility.ParseQueryString(uri.Query);

            string uriTimeIntervalType = uriQuery.Get("TimeIntervalType");
            string uriStartDate = uriQuery.Get("StartDate");
            string uriEndDate = uriQuery.Get("EndDate");

            int siteId;
            int buildingId, floorId, zoneId, fuelTypeId, timeInterval = -1;
            buildingId = 1;
            DateTime startDate, endDate;
            if (int.TryParse(uriQuery.Get("SiteId"), out siteId) == false ||
//                int.TryParse(uriQuery.Get("BuildingId"), out buildingId) == false ||
                int.TryParse(uriTimeIntervalType, out timeInterval) == false ||
                DateTime.TryParse(uriStartDate, out startDate) == false ||
                DateTime.TryParse(uriEndDate, out endDate) == false ||
                int.TryParse(uriQuery.Get("FuelTypeId"), out fuelTypeId) == false)
            {
                throw new Exception(string.Format("Not Found Parameters: {0},{1},{2}",
                    uriTimeIntervalType, uriStartDate, uriEndDate));
            }
            TimeInterval timeIntervalType = (TimeInterval)timeInterval;

            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;
                }
            }

            List<MonitoringPoint> list = new List<MonitoringPoint>();

            try
            {
                AddPointToListInLocation(list, siteId, fuelTypeId, buildingId, nullableFloorId, nullableZoneId);

                var values = CreateCalculationValues(startDate, endDate, timeIntervalType);
                foreach (var point in list)
                {
                    var pointValues = pointHistoryValueManager.GetPointValues(
                        siteId, point.FacilityCode, point.PropertyId,
                        timeIntervalType, startDate, endDate);

                    if (pointValues == null)
                        continue;

                    int index = 0;
                    CalculationValue p = null;
                    CalculationValue v = null;
                    for (var i = 0; i < values.Length; i++)
                    {
                        v = values[i];
                        if (p == null)
                        {
                            if (pointValues.Length <= index) break;

                            p = pointValues[index];
                        }

                        if (p.DateTime == v.DateTime)
                        {
                            v.Value += p.Value;
                            p = null;
                            index++;
                            if (pointValues.Length <= index) break;
                        }
                    }
                }
                return values;
            }
            catch (Exception)
            {
                throw;
            }

        }
   */
    }

    // hcLee 2015 03 30
    /*
    public class Building
    {
        public int SiteId { get; set; }
        public int BuildingId { get; set; }
        public int Name { get; set; }
    }; */

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

    // hcLee 2015 03 31
    public class MonitoringPointSType
    {
        public int SiteId { get; set; }
        public int FacilityCode { get; set; }
        public int PropertyId { get; set; }
        public int ServiceTypeId { get; set; }
        public int FuelTypeId { get; set; } // 2016 09 18 hcLee 추가
    };

    public class PointToLocation
    {
        public int SiteId { get; set; }
        public int FacilityCode { get; set; }
        public int PropertyId { get; set; }
        public int? BuildingId { get; set; }
        public int? FloorId { get; set; }
        public int? ZoneId { get; set; }
    };
                                                                          /*
    //hcLee 2015 07 16
    public class ZoneTempHumiData
    {
        public int SiteId { get; set; }
        public int? BuildingId { get; set; }
        public int? FloorId { get; set; }
        public int? ZoneId { get; set; }
    };                                                                                    
 */

    public class GetCenterSiteData_Param
    {
        public int TimeIntervalType { get; set; }
        public DateTime startDate { get; set; }
        public DateTime endDate { get; set; }
        //public Nullable<int> FacilityCode { get; set; }
        //public int FacilityCode { get; set; }
    };

    public class GetPrediction_Param
    {
        public int SiteId { get; set; }
        public int BuildingId { get; set; }
        public int FuelType { get; set; }
        public DateTime startDate { get; set; }
        public DateTime endDate{ get; set; }
        //public Nullable<int> FacilityCode { get; set; }
        //public int FacilityCode { get; set; }
    };
    // jhLee 2016-04-22
    public class FacilityCostInfo
    {
        public int SiteId { get; set; }
        public int FacilityCode { get; set; }
        public string RatedPowerConsumption { get; set; } 
        public Nullable<short> FuelTypeId { get; set; }
        public Nullable<short> ContractType { get; set; }
    };

    //2016 07 01 hcLee
    public class CenterSiteData
    {
        public int siteid { get; set; }
        public string name { get; set; }
        public List<CalculationResult> e_value_list { get; set; } // 오늘 전기
        public List<CalculationResult> g_value_list { get; set; } // 오늘 가스
        public Nullable<double> elec_current { get; set; } // 현재전기사용량
        public Nullable<double> elec_target { get; set; } // 현재전기목표
        public Nullable<double> gas_current { get; set; } // 현재가스사용량
        public Nullable<double> gas_target { get; set; } // 현재가스목표
        //public Nullable<double> kcal_target { get; set; } // 현재기준목표 kcal(전기+가스)
    };

}