// Created with MonoDevelop
//
//    Copyright (C) 2019 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 System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

using Hiperscan.Unix;

namespace Hiperscan.Common.Checksum
{

    public class FileChecksum : Hiperscan.Common.Checksum.BaseChecksum
    {
        public FileChecksum(HashType type, string base_dir, string salt = null, string api_key_hash = null, string api_key = null)
            : base(type, salt, api_key_hash, api_key)
        {
            this.BaseDir = Path.GetFullPath(base_dir);
            this.CheckSumFileName = Path.Combine(this.BaseDir, string.Format("Checksum_{0}.txt", type));
        }

        public override string ComputeHash()
        {
            List<byte> buf = this.GenerateSalt();

            List<string> files = new List<string>(FileIO.GetFiles(this.BaseDir, "*", SearchOption.AllDirectories));
            files.Sort(StringComparer.InvariantCulture);

            foreach (string fname in files)
            {
                if (fname == this.CheckSumFileName)
                    continue;

                bool is_relevant_file = this.FileFilter.Count == 0;

                foreach (Regex regex in this.FileFilter)
                {
                    if (regex.Match(Path.GetFileName(fname)).Success == true)
                    {
                        is_relevant_file = true;
                        break;
                    }
                }

                if (is_relevant_file == false)
                    continue;
   
                buf.AddRange(FileIO.ReadFileAsBytes(fname));
            }

            return BitConverter.ToString(this.CurrentHashAlogrithm.ComputeHash(buf.ToArray()));
        }

        public void CreateCheckSumFile()
        {
            using (TextWriter writer = FileIO.CreateTextFile(this.CheckSumFileName))
            {
                writer.Write(this.ComputeHash());
            }
        }

        public override bool Verifiy() => this.ComputeHash() == FileIO.ReadFileToEndWithEncodingFromBOM(this.CheckSumFileName);

        private string BaseDir          { get; set; }
        private string CheckSumFileName { get; set; }
        public List<Regex> FileFilter   { get; set; } = new List<Regex>();
    }
}
