using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Collections.ObjectModel;

namespace Telerik.Windows.GridView.Tests
{
    public partial class BindingTestHelper
    {
        public static IList<OrderWithNullableData> GetSampleDataWithNullableProperties(int count)
        {
            List<OrderWithNullableData> orderWithNullableDatas = new List<OrderWithNullableData>();
            for (int i = 0; i < count; i++)
            {
                orderWithNullableDatas.Add(new OrderWithNullableData
                                               {
                                                   ID = i,
                                                   IsCancelled = null,
                                                   OrderDate = null,
                                                   OrderNumber = null
                                               });
            }
            return orderWithNullableDatas;
        }

        public static ObservableCollection<OrderPC> GetSampleObservableOrderPCCollection(int count)
        {
            ObservableCollection<OrderPC> ordersPC = new ObservableCollection<OrderPC>();
            for (int i = 0; i < count; i++)
            {
                ordersPC.Add(new OrderPC
                                 {
                                     ID = i,
                                     Description = "Desc " + i
                                 });
            }
            return ordersPC;
        }

        public static IList<Order> GetSampleOrdersList(int count)
        {
            IList<Order> orders = new List<Order>();
            for (int i = 0; i < count; i++)
            {
                orders.Add(new Order
                {
                    ID = i,
                    Description = "Desc " + i
                });
            }
            return orders;
        }

        public static IList GetSampleHierarchy()
        {
            Func<int, List<Order>> ordersGen  = customerIndex =>
                                                    {
                                                        var q = from i in Enumerable.Range(1, 10)
                                                                select new Order { 
                                                                                     ID = (10 * customerIndex) + i, 
                                                                                     Description = "Order " + (10 * customerIndex + i) };

                                                        return q.ToList();
                                                    };

            var t = from i in Enumerable.Range(1, 10)
                    select new Customer { Age = i, JobCode = i, Name = "Customer " + i, Orders = ordersGen(i) };

            return t.ToList();
        }

        public static ObservableCollection<Customer> GetSampleObservableHierarchy()
        {
            ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
            foreach (Customer item in GetSampleHierarchy())
            {
                customers.Add(item);
            }
            return customers;
        }

        public static ObservableCollection<FullName> GetSampleObservableStringCollection(int count)
        {
            ObservableCollection<FullName> fullNames = new ObservableCollection<FullName>();
            for (int i = 0; i < count; i++)
            {
                fullNames.Add(new FullName
                                  {
                                      FirstName = "John " + i,
                                      MiddleName = "Doe " + i,
                                      LastName = "Smith " + i
                                  });
            }
            return fullNames;
        }

        public static ObservableCollection<Customer> GetSampleObservableCollection(int count)
        {
            ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
            for (int i = 0; i < count; i++)
            {
                customers.Add(new Customer
                {
                    Age = i,
                    Boolean = Convert.ToBoolean(i % 2),
                    Name = "Customer " + i,
                    JobCode = i
                });
            }
            return customers;
        }

        public static ObservableCollection<Customer> GetSampleObservableCollectionForGrouping()
        {
            ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
            IEnumerable<Customer> source = GetSampleDataForGrouping();
            foreach (Customer customer in source)
            {
                customers.Add(customer);
            }
            return customers;
        }

        public static IEnumerable<Customer> GetSampleDataWithRandomValues(int count)
        {
            Random r = new Random();
            IList<Customer> data = new List<Customer>();
            for (int i = 0; i < count; i++)
            {
                Customer c = new Customer
                   {
                       Age = r.Next(0, 99),
                       Boolean = Convert.ToBoolean(r.Next(0, 1)),
                       Name = "Customer " + r.Next(10000),
                       JobCode = r.Next(10000),
                       RegistrationDate = DateTime.Today.AddDays(r.Next(10000))
                   };
                data.Add(c);
            }
            return data;
        }
        
        public static IEnumerable<Customer> GetSampleData(int count)
        {
            return from index in Enumerable.Range(1, count)
                   select new Customer
                              {
                                  Age = index,
                                  Boolean = Convert.ToBoolean(index % 2),
                                  Name = "Customer " + index,
                                  JobCode = index,
                                  RegistrationDate = DateTime.Today
                              };
        }

        public static IEnumerable<Customer> GetSampleDataForGrouping(int count)
        {
            return from index in Enumerable.Range(1, count)
                   select new Customer
                              {
                                  Age = index % 2,
                                  Boolean = Convert.ToBoolean(index % 2),
                                  Name = "Customer " + index,
                                  JobCode = index % 3
                              };
        }

        public static IEnumerable<Customer> GetSampleDataForGrouping()
        {
            Customer customer1 = new Customer { JobCode = 0, Age = 15 };

            Customer customer2 = new Customer { JobCode = 0, Age = 15 };

            Customer customer3 = new Customer { JobCode = 0, Age = 16 };

            Customer customer4 = new Customer { JobCode = 1, Age = 15 };

            Customer customer5 = new Customer { JobCode = 1, Age = 16 };

            Customer customer6 = new Customer { JobCode = 1, Age = 17 };

            Customer customer7 = new Customer { JobCode = 1, Age = 16 };

            return new List<Customer> { customer1, customer2, customer3, customer4, customer5, customer6, customer7 };
        }

        public const string CustomerXml = @"
<Customers>
    <Customer>
		<Code>1234</Code>
		<Name>EPI</Name>
		<Country>1</Country>
		<IsRegular>True</IsRegular>
	</Customer>
	<Customer>
		<Code>3234</Code>
		<Name>Paullllllllllllllllllllllllllllllllllllll</Name>
		<Country>2</Country>
		<IsRegular>False</IsRegular>
	</Customer>
</Customers>";

        public class Customer : INotifyPropertyChanged
        {
            private string name;
            private int age;
            private int? jobCode;
            private DateTime registrationDate;

            public string Name
            {
                get {
                    return name;
                }
                set
                {
                    if (name != value)
                    {
                        name = value;
                        this.OnPropertyChanged("Name");
                    }
                }
            }

            public FullName FullName
            {
                get;
                set;
            }

            public int Age
            {
                get
                {
                    return this.age;
                }
                set
                {
                    if (value != this.age)
                    {
                        this.age = value;
                        this.OnPropertyChanged("Age");
                    }
                }
            }

            public int? JobCode
            {
                get
                {
                    return this.jobCode;
                }
                set
                {
                    if (value != this.jobCode)
                    {
                        this.jobCode = value;
                        this.OnPropertyChanged("JobCode");
                    }
                }
            }

            private bool boolean;

            public bool Boolean
            {
                get
                {
                    return this.boolean;
                }
                set
                {
                    this.boolean = value;
                    this.OnPropertyChanged("Boolean");
                }
            }

            public DateTime RegistrationDate
            {
                get
                {
                    return this.registrationDate;
                }
                set
                {
                    if (value != this.registrationDate)
                    {
                        this.registrationDate = value;
                        this.OnPropertyChanged("RegistrationDate");
                    }
                }
            }

            public List<Order> Orders
            {
                get;
                set;
            }

            public IList<Customer> RelatedCustomers
            {
                get;
                internal set;
            }

            public override string ToString()
            {
                return string.Format("FullName: {0}, Age: {1}, JobCode: {2}", this.FullName, this.Age, this.JobCode);
            }

            public static IList<Customer> GetAll()
            {
                return GetSampleData(10).ToList();
            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }

            public override bool Equals(object obj)
            {
                var other = obj as Customer;
                if (other != null)
                {
                    return this.Equals(other);
                }

                return false;
            }

            public bool Equals(Customer other)
            {
                if (ReferenceEquals(null, other)) return false;
                if (ReferenceEquals(this, other)) return true;

                return 
                    Equals(this.Name, other.Name) && 
                    Equals(this.Age, other.Age);
            }
        }

        public class FullName
        {
            public string FirstName
            {
                get;
                set;
            }

            public string MiddleName
            {
                get;
                set;
            }

            public string LastName
            {
                get;
                set;
            }

            public bool UseMiddleName
            {
                get;
                set;
            }
        }

        public class Order
        {
            public int? ID
            {
                get;
                set;
            }

            public string Description
            {
                get;
                set;
            }

			public override string ToString()
			{
				return string.Format("{0} {1}", this.ID, this.Description);
			}
        }

        public class OrderPC : INotifyPropertyChanged
        {
            private int? id;
            private string description;

            public int? ID
            {
                get
                {
                    return this.id;
                }
                set
                {
                    if (this.id != value)
        {
                        this.id = value;
                        this.PropertyChanged(this, new PropertyChangedEventArgs("ID"));
                    }
                }
            }

            public string Description
            {
                get
                {
                    return this.description;
                }
                set
                {
                    if (this.description != value)
                    {
                        this.description = value;
                        this.PropertyChanged(this, new PropertyChangedEventArgs("Description"));
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged = delegate { };
        }

        public class CustomerListWithCustomIndexer : List<Customer>
        {
            public new string this[int index]
            {
                get
                {
                    return base[index].Name;
                }
            }
        }

        public class OrderWithNullableData
        {
            public int ID
            {
                get;
                set;
            }

            public decimal? OrderNumber
            {
                get;
                set;
            }

            public DateTime? OrderDate
            {
                get;
                set;
            }

            public bool? IsCancelled
            {
                get;
                set;
            }
        }
    }
}