﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace PhotoEditor.Image
{
    public abstract class Processor<TPage, TProcessor, TImageData> : IUpdate
    {
        private TPage _page;
        private List<ControlGroup<TProcessor>> _controlGroups;
        //private TImageData _sourceImage;
        protected TImageData ProcessedImage;
        private TImageData _cachedImage;

        public void Init(TImageData imageData)
        {
            _page = CreatePage();
            //_sourceImage = imageData;
            ProcessedImage = PreProcessImage(imageData);
            _controlGroups = CreateControlGroups();

            var elements = new List<UIElement>();
            foreach (var controlGroup in _controlGroups)
            {
                var label = new Label();
                label.Content = controlGroup.Name;
                label.Foreground = new SolidColorBrush(Color.FromArgb(0xFF, 0x33, 0x33, 0x33));
                label.FontSize = 24;
                elements.Add(label);

                elements.AddRange(controlGroup.Controls.Select(control => control.GetElement(this)));

                var separator = new Separator {Height = 3};
                elements.Add(separator);
            }
            UpdateProcessors(elements);

            CacheNonContinuous();

            AfterInit();
        }

        public TPage GetPage()
        {
            return _page;
        }

        public void CacheNonContinuous()
        {
            var image = ProcessedImage;
            var processor = GetProcessor(image);
            foreach (var control in _controlGroups.SelectMany(
                controlGroup => controlGroup.Controls.Where(control => control.Enabled && !control.Continuous)))
            {
                control.Apply(processor);
            }
            _cachedImage = FinishProcessing(processor);
            ProcessContinuous();
        }

        public void ProcessContinuous()
        {
            var image = _cachedImage;
            var processor = GetProcessor(image);
            foreach (var control in _controlGroups.SelectMany(
                controlGroup => controlGroup.Controls.Where(control => control.Enabled && control.Continuous)))
            {
                control.Apply(processor);
            }
            var finishedImage = FinishProcessing(processor);
            UpdateImage(finishedImage);
        }

        protected abstract void AfterInit();

        protected abstract TPage CreatePage();

        protected abstract List<ControlGroup<TProcessor>> CreateControlGroups();

        protected abstract TImageData PreProcessImage(TImageData image);

        protected abstract TProcessor GetProcessor(TImageData image);

        protected abstract TImageData FinishProcessing(TProcessor processor);

        protected abstract void UpdateProcessors(List<UIElement> elements);

        protected abstract void UpdateImage(TImageData image);
    }
}
