// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2022, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using Hiperscan.AnalysisModule.Identification;
using Hiperscan.ApoIdentCommon.ApoConfig.IO;
using Hiperscan.Unix;

namespace Hiperscan.ApoIdentCommon.ApoConfig.Cache
{
    public abstract class CacheManagement<T, U>
    {
        protected const string INVALID_SUBSTANCE_ID = "INVALID_SUBSTANCE_ID";

        protected abstract U GetDefaultValue();
        protected abstract U ConvertFromString(string value);
        protected abstract string ConvertToString(U value);
        protected abstract bool StateChanged();
        protected abstract U CloneCurrentValue();

        public void LoadAutoCompletion(string file_name, bool directory_changed)
        {
            EntryWriter<T> tmp = new EntryWriter<T>(file_name);

            if (directory_changed)
            {
                if (tmp.FoundData)
                {
                    this.Entries = tmp;
                }
                else
                {
                    this.Entries.SafetyWrite(file_name);
                }
            }
            else
            {
                this.Entries = tmp;
            }
        }

        public virtual void Reset()
        {
            this.SubstanceId = CacheManagement<T,U>.INVALID_SUBSTANCE_ID;
            this.CurrentValue = this.GetDefaultValue();
            this.InitialValue = this.GetDefaultValue();
            this.FoundOldSubstanceKey = false;
        }

        public void SetInitialValue(IdentSubstance substance, U value)
        {
            this.SubstanceId = substance.Id;

            if (this.Entries.ContainsKey(this.SubstanceId))
            {
                this.CurrentValue = this.ConvertFromString(this.Entries.GetValue(this.SubstanceId));
            }
            else
            {
                string old_key = substance.ModelClass.Name + substance.Id;
                if (this.Entries.ContainsKey(old_key))
                {
                    this.CurrentValue = this.ConvertFromString(this.Entries.RemoveValue(old_key));
                    this.Entries.AddValue(this.SubstanceId, this.CurrentValue.ToString());
                    this.FoundOldSubstanceKey = true;
                }
                else
                {
                    this.CurrentValue = value;
                }
            }

            this.InitialValue = this.CloneCurrentValue();
        }

        public void SaveAutoCompletion(string file_name)
        {
            if (this.SubstanceId == CacheManagement<T, U>.INVALID_SUBSTANCE_ID)
            return;

            if (false == this.StateChanged() && FileIO.ExistsFile(file_name) && false == this.FoundOldSubstanceKey)
                return;

            this.Entries.AddValue(this.SubstanceId, this.ConvertToString(this.CurrentValue));
            this.Entries.SafetyWrite(file_name);
            this.FoundOldSubstanceKey = false;
        }


        public U CurrentValue { get; set; }
        protected U InitialValue { get; set; }
        private string SubstanceId { get; set; }
        protected EntryWriter<T> Entries { get; set; }
        private bool FoundOldSubstanceKey { get; set; }
    }
}
