using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using FLY.Thick.Base.IService;
using Misc;

namespace FLY.Thick.Base.Client
{
    public class BoltCreateInfo
    {
        public BoltCreateInfo() 
        {
         
        }

        #region IBoltCreateInfoService
        private int poslength;
        public int PosLength
        {
            get
            {
                return poslength;
            }
            set
            {
                if (poslength != value)
                {
                    poslength = value;
                    NotifyPropertyChanged("PosLength");
                }
            }
        }
        private int boltwidth;
        public int BoltWidth
        {
            get
            {
                return boltwidth;
            }
            set
            {
                if (boltwidth != value)
                {
                    boltwidth = value;
                    NotifyPropertyChanged("BoltWidth");
                }
            }
        }
        private int boltno1st;
        public int BoltNo1st
        {
            get
            {
                return boltno1st;
            }
            set
            {
                if (boltno1st != value)
                {
                    boltno1st = value;
                    NotifyPropertyChanged("BoltNo1st");
                }
            }
        }
        private int boltinterval;
        public int BoltInterval
        {
            get
            {
                return boltinterval;
            }
            set
            {
                if (boltinterval != value)
                {
                    boltinterval = value;
                    NotifyPropertyChanged("BoltInterval");
                }
            }
        }
        private int boltscnt;
        public int BoltsCnt
        {
            get
            {
                return boltscnt;
            }
            set
            {
                if (boltscnt != value)
                {
                    boltscnt = value;
                    NotifyPropertyChanged("BoltsCnt");
                }
            }
        }
        private ObservableCollection<CustomBolt> custom = new ObservableCollection<CustomBolt>();
        public ObservableCollection<CustomBolt> Custom
        {
            get { return custom; }
        }
        #endregion 


        #region INotifyPropertyChanged 成员
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region 自动生成螺丝映像
        public enum CreateAutoMapReturn 
        {
            OK,
            Error_Length,
            Error_Width,
            Error_Interval,
            Error_Customs

        }
        /// <summary>
        /// 自动分区
        /// </summary>
        /// <param name="boltmap">得出的结果</param>
        /// <param name="firstBoltNo">第1分区号</param>
        /// <param name="length">总脉冲长</param>
        /// <param name="width">分区宽度</param>
        public CreateAutoMapReturn CreateAutoMap(IBoltMapService boltmap, int length, int width, int firstBoltNo)
        {
            if (length <= 0) return CreateAutoMapReturn.Error_Length;
            if (width <= 0) return CreateAutoMapReturn.Error_Width;
            if (width < 10)
                width = 100;

            int cnt = length / width;


            boltmap.Bolts.Clear();
            int last=-1;
            //生成
            for (int i = 0; i < cnt; i++)
            {
                int begin = last + 1;
                int end = begin + width;

                if (begin < 0) begin = 0;
                if (end >= length) end = length - 1;

                if (i == 0)
                    begin = 0;

                if (i == cnt - 1)
                    end = length - 1;

                last = end;
                boltmap.Bolts.Add(new Range() { Begin = begin, End = end });
            }
            boltmap.FirstBoltNo = firstBoltNo;
            return CreateAutoMapReturn.OK;
        }
        /// <summary>
        /// 自动分区
        /// </summary>
        /// <param name="boltmap">得出的结果</param>
        /// <param name="firstBoltNo">第1分区号</param>
        /// <param name="length">总脉冲长</param>
        /// <param name="width">分区宽度</param>
        /// <param name="interval">分区间隔</param>
        public CreateAutoMapReturn CreateAutoMap(IBoltMapService boltmap, int length, int width, int firstBoltNo, int interval) 
        {
            if (length <= 0) return CreateAutoMapReturn.Error_Length;
            if (width <= 0) return CreateAutoMapReturn.Error_Width;
            if (interval <= 0) return CreateAutoMapReturn.Error_Interval;
            int cnt = length / interval + 1;
            if (width < 10)
                width = 100;

            //补齐
            List<int> center = new List<int>();
            int last = -interval / 2;
            for (int i = 0; i < cnt; i++)
            {
                int pos = last+interval;
                center.Add(pos);
                last = pos;
            }

            return CreateAutoMap_full(boltmap, firstBoltNo, length, width, center);
        }

        /// <summary>
        /// 使用全的螺丝中心位置 自动生成螺丝映像, 第一个螺丝Begin=0, 最后一个螺丝End=length-1
        /// </summary>
        /// <param name="firstBoltNo">第一个分区号</param>
        /// <param name="length">总脉冲数</param>
        /// <param name="width">螺丝宽度</param>
        /// <param name="center">全的螺丝中心位置</param>
        /// <returns></returns>
        private CreateAutoMapReturn CreateAutoMap_full(IBoltMapService boltmap, int firstBoltNo, int length, int width, IEnumerable<int> center)
        {
            boltmap.Bolts.Clear();
            //生成
            for (int i = 0; i < center.Count(); i++)
            {
                int begin = center.ElementAt(i) - width / 2;
                int end = begin + width;

                if (begin < 0) begin = 0;
                if (end >= length) end = length - 1;

                if (i == 0)
                    begin = 0;

                if (i == center.Count() - 1)
                    end = length - 1;

                boltmap.Bolts.Add(new Range() { Begin = begin, End = end });
            }
            boltmap.FirstBoltNo = firstBoltNo;
            return CreateAutoMapReturn.OK;
        }

        /// <summary>
        /// 根据已知的分区号对应脉冲位，自动分区。 cusbolts 是从小到大排列的;
        /// cusbolts只有一个也是可以的
        /// </summary>
        /// <param name="length"></param>
        /// <param name="width"></param>
        /// <param name="bolts"></param>
        /// <returns></returns>
        public CreateAutoMapReturn CreateAutoMap(IBoltMapService boltmap, int length, int width, IEnumerable<CustomBolt> cusbolts)
        {
            if (cusbolts.Count() < 1)
            {
                return CreateAutoMapReturn.Error_Customs;
            }

            if (length < 0) return CreateAutoMapReturn.Error_Length;



            //补齐
            List<CustomBolt> fullbolts = new List<CustomBolt>();


            for (int i = 0; i < cusbolts.Count() - 1; i++)
            {
                CustomBolt c0 = cusbolts.ElementAt(i);
                CustomBolt c1 = cusbolts.ElementAt(i + 1);

                int d_no = c1.No - c0.No;
                int d_pos = c1.Position - c0.Position;

                double dd_pos = (double)d_pos / d_no;

                if (width < dd_pos)
                    width = (int)dd_pos;

                for (int j = 0; j < d_no; j++)
                {
                    int no = j + c0.No;
                    int pos = d_pos * j / d_no + c0.Position;

                    fullbolts.Add(new CustomBolt() { No = no, Position = pos });
                }
            }
            CustomBolt clast = cusbolts.Last() as CustomBolt;
            fullbolts.Add(new CustomBolt() { No = clast.No, Position = clast.Position });

            if (width < 10)
                width = 100;

            //插入头
            {
                int dis;
                if (fullbolts.Count == 1)
                {
                    dis = width;
                }
                else
                {
                    CustomBolt f0 = fullbolts.First() as CustomBolt;
                    CustomBolt f1 = fullbolts.ElementAt(1) as CustomBolt;
                    dis = f1.Position - f0.Position;
                }
                int no = fullbolts.First().No - 1;
                int pos = fullbolts.First().Position - dis;
                while (pos > width / 2)
                {
                    fullbolts.Insert(0, new CustomBolt() { No = no, Position = pos });
                    no--;
                    pos -= dis;
                }
            }
            //插入尾
            {
                int dis;
                if (fullbolts.Count == 1)
                {
                    dis = width;
                }
                else
                {
                    CustomBolt f0 = fullbolts.ElementAt(fullbolts.Count - 2) as CustomBolt;
                    CustomBolt f1 = fullbolts.Last() as CustomBolt;
                    dis = f1.Position - f0.Position;
                }

                int no = fullbolts.Last().No + 1;
                int pos = fullbolts.Last().Position + dis;

                while (pos < (length - width / 2))
                {
                    fullbolts.Add(new CustomBolt() { No = no, Position = pos });
                    no++;
                    pos += dis;
                }
            }



            //生成
            int firstBoltNo = fullbolts.First().No;
            var center = from bolt in fullbolts select bolt.Position;
            return CreateAutoMap_full(boltmap, firstBoltNo, length, width, center);
        }

        #endregion
    }
    public class CustomBolt
    {
        static CustomBolt()
        {
            Misc.SaveToXmlHepler.Regist(typeof(CustomBolt));
        }
        private int no;
        public int No
        {
            get
            {
                return no;
            }
            set
            {
                if (no != value)
                {
                    no = value;
                    NotifyPropertyChanged("No");
                }
            }
        }
        private int position;
        public int Position
        {
            get
            {
                return position;
            }
            set
            {
                if (position != value)
                {
                    position = value;
                    NotifyPropertyChanged("Position");
                }
            }
        }

        #region INotifyPropertyChanged 成员
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
