﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RecnikWPF
{
    public delegate void ObjavaBrojaElemenata(int brojElemenata);

    public delegate bool Filter<Kljuc, Vrednost>(Par<Kljuc, Vrednost> par)
        where Kljuc : class, IEquatable<Kljuc>
        where Vrednost : class, IEquatable<Vrednost>;

    public class Recnik<Kljuc, Vrednost> : IEnumerable<Par<Kljuc, Vrednost>>
        where Kljuc : class, IEquatable<Kljuc>
        where Vrednost : class, IEquatable<Vrednost>
    {
        public event ObjavaBrojaElemenata PromenaBrojaElemenata;

        private List<Par<Kljuc, Vrednost>> parovi;

        public Recnik()
        {
            parovi = new List<Par<Kljuc, Vrednost>>();
        }

        public Vrednost this[Kljuc kljuc]
        {
            set
            {
                Dodaj(kljuc, value);
            }

            get
            {
                foreach (var par in parovi)
                {
                    if (par.kljuc.Equals(kljuc))
                    {
                        return par.vrednost;
                    }
                }

                return default(Vrednost);
            }
        }

        public void Dodaj(Kljuc kljuc, Vrednost vrednost)
        {
            foreach (var par in parovi)
            {
                if (par.kljuc.Equals(kljuc))
                {
                    par.vrednost = vrednost;
                    return;
                }
            }

            parovi.Add(new Par<Kljuc, Vrednost>(kljuc, vrednost));

            if (PromenaBrojaElemenata != null)
                PromenaBrojaElemenata(parovi.Count);

        }

        public static Recnik<Kljuc, Vrednost> operator +(Recnik<Kljuc, Vrednost> recnik1, Recnik<Kljuc, Vrednost> recnik2)
        {
            Recnik<Kljuc, Vrednost> noviRecnik = new Recnik<Kljuc, Vrednost>();

            foreach (var item in recnik1)
            {
                noviRecnik.Dodaj(item.kljuc, item.vrednost);
            }

            foreach (var item in recnik2)
            {
                noviRecnik.Dodaj(item.kljuc, item.vrednost);
            }

            return noviRecnik;
        }

        public IEnumerator<Par<Kljuc, Vrednost>> GetEnumerator()
        {
            foreach (var item in parovi)
            {
                yield return item;
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public static implicit operator List<Kljuc>(Recnik<Kljuc, Vrednost> parovi)
        {
            List<Kljuc> kljucevi = new List<Kljuc>();

            foreach (var item in parovi)
            {
                kljucevi.Add(item.kljuc);
            }

            return kljucevi;
        }

        public IEnumerable<Par<Kljuc, Vrednost>> Filtriraj(Filter<Kljuc, Vrednost> filterFunkcija)
        {
            foreach (var item in this)
            {
                if (filterFunkcija(item))
                {
                    yield return item;
                }
            }
        }
    }
}
