using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage.Table;

namespace TableStorageExample
{
    class Program
    {
        #region privateFields
        private static readonly List<Person> peopleList = new List<Person>();
        private static IEnumerable<IGrouping<string, Person>> groupedByCity;
        private static List<Task> listOfTasks = new List<Task>();
        private static readonly CloudTableClient client = SharedStorage.StorageConst.GetTableClient;
        private static readonly CloudTable table = client.GetTableReference("SampleTable");
        #endregion
        static void Main(string[] args)
        {
            

            table.CreateIfNotExists();

            //GetPersons();

            //GroupPersonByCity();

            //UploadToCloudTableBatch();

            //WaitForTasks();

            var persons = GetByCity("Warszawa");
            foreach (var person in persons)
            {
                Console.WriteLine(person.FirstName + " " + person.LastName);
            }

            var subQuery = GetSubQuery();

            foreach (var person in subQuery)
            {
                Console.WriteLine(person.FirstName + " " + person.LastName);
            }

            GetInPages();
            Console.ReadKey();
        }

        private static void WaitForTasks()
        {
            while (!Task.WhenAll(listOfTasks).IsCompleted)
            {
                
            }
        }

        private static void UploadToCloudTableBatch()
        {
            foreach (var personByCity in groupedByCity)
            {
                TableBatchOperation operation = new TableBatchOperation();
                foreach (var person in personByCity)
                {
                    operation.Add(TableOperation.Insert(person));
                }
                var city = personByCity;
                listOfTasks.Add(
                    table.ExecuteBatchAsync(operation)
                        .ContinueWith((result) => { Console.WriteLine("Partition Key {0} completed", city.Key); }));
            }
        }

        private static void GroupPersonByCity()
        {
            groupedByCity = peopleList.GroupBy(person => person.PartitionKey);
        }

        private static void GetPersons()
        {
            using (StreamReader stream = new StreamReader(@"C:\Users\Lukas_000\Downloads\names.csv"))
            {
                String line;
                while ((line = stream.ReadLine()) != null)
                {
                    peopleList.Add(GetPerson(line));
                }
            }
        }

        private static Person GetPerson(String csvRow)
        {
            var splited = csvRow.Split(',');
            return new Person
            {
                FirstName = splited[0],
                LastName = splited[2],
                MiddleName = splited[1],
                PartitionKey = splited[3],
                ZipCode = splited[4],
                Telephone = splited[5],
                CredidCard = splited[6],
                NationalId = splited[7]

            };


        }

        private static List<Person> GetByCity(String city)
        {
            TableQuery<Person> query =
                new TableQuery<Person>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal,
                    "Bielsko-Biała"));

            var queryResult = table.ExecuteQuery(query);

            return queryResult.ToList();
        }

        private static List<PersonMin> GetSubQuery()
        {

            TableQuery<DynamicTableEntity> subQuery =
                new TableQuery<DynamicTableEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey",QueryComparisons.Equal,"Bielsko-Biała")).Select(new String[] {"FirstName", "LastName"});
            EntityResolver<PersonMin> resolver = (pk, rk, ts, props, etag) => new PersonMin
            {
                City = pk,
                FirstName = props["FirstName"].StringValue,
                LastName = props["LastName"].StringValue
            };

            return table.ExecuteQuery(subQuery, resolver).ToList();
        }

        private static void GetInPages()
        {
            TableQuery<Person> query = new TableQuery<Person>();
            TableContinuationToken token = null;

            do
            {
                
                TableQuerySegment<Person> segment = table.ExecuteQuerySegmented(query, token);
                token = segment.ContinuationToken;
            } while (token != null);
        }
    }

    public class Person : TableEntity
    {
        public Person()
        {
            RowKey = Guid.NewGuid().ToString("N");
        }

        public String FirstName { get; set; }
        public String MiddleName { get; set; }
        public String LastName { get; set; }
        public String ZipCode { get; set; }
        public String Telephone { get; set; }
        public String CredidCard { get; set; }
        public String NationalId { get; set; }
    }


    public class PersonMin
    {
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public String City { get; set; }
    }
}
