using BoFilTest.Utils;
using Optional;
using Optional.Unsafe;
using System;

namespace BoFilTest.Domain
{
    public class DataModel
    {
        public DataModel(EventBus eventBus, Configuration config, string version)
        {
            this.MeasurementProtocol = new MeasurementProtocol(eventBus);
            this.Form = new Form();
            this.Config = config;
            this.Store = new Store();
            this.AfterTestForm = new AfterTestForm();
            this.Version = version;

            LoadDefaults();

            eventBus.Subscribe<TestFinished>(message =>
            {
                AfterTestForm.Reset();
                Timings = Option.Some(message.Timings);
            });
        }

        public void LoadDefaults()
        {
            // Load last-used values by default
            var defaults = this.Store.LastDefaults();
            if (defaults == null)
            {
                defaults = Config.Defaults();
            }
            Form.LoadDefaults(defaults);
        }

        public void LoadConfiguredDefaults()
        {
            Form.LoadDefaults(Config.Defaults());
        }

        public void SetupNew()
        {
            Form.SetupNew();
        }

        public MeasurementProtocol MeasurementProtocol { get; }
        public Form Form { get; }
        internal Configuration Config { get; }
        internal Store Store { get; }
        public AfterTestForm AfterTestForm { get; }
        public string Version { get; }
        public Option<TestTimings> Timings { get; private set; }
        public Option<double> GasIntegralForArea
        {
            get
            {
                if (Form.FilterArea <= 0.0 || !MeasurementProtocol.GasIntegral.HasValue)
                    return Option.None<double>();

                var integralLiters = MeasurementProtocol.GasIntegral.ValueOrFailure();
                // Liters is 1/1000 m³, cm² is 1/10000 m² - so the final value for m is:
                return (10 * integralLiters / Form.FilterArea).Some();
            }
        }
            
        public string TestNumber => String.Format("{0}{1:0000000.}", Config.TestNumberPrefix(), Store.GetTestNumberCounter());
    }
}
