﻿using System;
using System.Collections.Generic;
using System.Linq;
using SDS.Core;

namespace ExampleApp
{
    class Program
    {
        static Random r = new Random();

        static void Main(string[] args)
        {
            SingleFileDataStore<Foo, int> fooStore = new SingleFileDataStore<Foo, int>(@"c:\temp\temp2.txt", item => item.A);

            //// clear all items
            //foreach (var foo in fooStore.All())
            //{
            //    fooStore.Delete(foo);
            //}

            //// generate random foos
            //var foos = GiveMeFoos(10);

            //// Insert a bunch foos
            //foreach (var foo in foos)
            //{
            //    try
            //    {
            //        // Since these are randomly generated items, potential for a clash of ids.
            //        fooStore.Create(foo);

            //        // for good measure, lets 'create' the same item twice and watch it fail
            //        // (this will not get rolled back as part of try/catch since current implementation writes to disk instantly)
            //        fooStore.Create(foo);
            //    }
            //    catch (Exception ex)
            //    {
            //        Console.WriteLine("Failed to update fooStore: {0}", ex.Message);
            //    }
            //}

            // write out all ours foos (potentially less than we created if Ids were duplicated)

            foreach (Foo foo in fooStore.All())
            {
                Console.WriteLine("ID:{3}\t{0}: {1} (\"{2}\")", foo.A, foo.B, foo.C, fooStore.GetId(foo));
            }
            Console.WriteLine();
            foreach (Foo foo in fooStore.Get(x => x.B > 0.5))
            {
                Console.WriteLine("{0}: {1} (\"{2}\")", foo.A, foo.B, foo.C);
            }
            Console.WriteLine();
            fooStore.Delete(x => x.B <= 0.5);
            foreach (Foo foo in fooStore.All())
            {
                Console.WriteLine("{0}: {1} (\"{2}\")", foo.A, foo.B, foo.C);
            }

            //// more complex items
            //SingleFileDataStore<Bar, Guid> barStore = new SingleFileDataStore<Bar, Guid>(@"c:\temp\bars.txt", b => b.Id);
            //barStore.DeleteAll();

            //for (int i = 0; i < 100; i++)
            //{
            //    barStore.Create(new Bar(Guid.NewGuid(), GiveMeFoos(10).ToList()));
            //}

            //foreach (Bar bar in barStore.All())
            //{
            //    Console.WriteLine(bar.Id);
            //    foreach (Foo foo in bar.Foos)
            //    {
            //        Console.WriteLine("\t{0}", foo.C);
            //    }
            //}

            //// silly ids
            //SingleFileDataStore<Bar, string> barStore2 = new SingleFileDataStore<Bar, string>(@"c:\temp\bars2.txt", b => string.Concat(b.Foos.Select(x => x.C)));

            //for (int i = 0; i < 10; i++)
            //{
            //    Bar b = new Bar(Guid.NewGuid(), GiveMeFoos(5).ToList());
            //    Console.WriteLine("Created item: {0}", barStore2.GetId(b));
            //    barStore2.Create(b);
            //}

            //foreach (Bar bar in barStore2.All())
            //{
            //    Console.WriteLine(barStore2.GetId(bar));
            //}
        }

        static IEnumerable<Foo> GiveMeFoos(uint n)
        {
            string stringChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

            for (int i = 0; i < n; i++)
            {
                string randomString = null;
                for (int j = 0; j < 8; j++)
                {
                    randomString = string.Concat(randomString, stringChars[r.Next(stringChars.Length)]);
                }

                yield return new Foo(r.Next(int.MaxValue), r.NextDouble(), randomString);
            }
        }

        class Foo
        {
            public int A { get; set; }
            public double B { get; set; }
            public string C { get; set; }

            public Foo()
            {
            }
            public Foo(int i, double d, string s)
            {
                this.A = i;
                this.B = d;
                this.C = s;
            }
        }

        class Bar
        {
            public Bar()
                :this(Guid.Empty, new List<Foo>())
            {
            }

            public Bar(Guid g, List<Foo> foos) 
            {
                this.Id = g;
                this.Foos = foos;
            }

            public Guid Id { get; set; }
            public List<Foo> Foos { get; set; }
        }

    }
}
