// Created with MonoDevelop
//
//    Copyright (C) 2023 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.Linq;
using Hiperscan.Unix;

namespace Hiperscan.Common.SerialPorts
{
    public partial class ComPort
    {
        public int Write(string text)
        {
            return this.Write(this.encoding.GetBytes(text));
        }

        public int Write(byte[] array)
        {
            return this.Write(array, false);
        }

        private int Write(byte[] array, bool from_write_buffer)
        {
            lock (this)
            {
                DateTime now = DateTime.Now;
                this.CheckDisosed();

                try
                {
                    this.State = ComPortState.Writing;

                    if (array == null || array.Length == 0)
                        return 0;

                    byte[] total_bytes = this.AddAttachment(array);
                    if (from_write_buffer == false)
                        total_bytes = this.AddAttachment(array);

                    if (total_bytes.Length > ComPort.MAX_BLOCK_LENGTH)
                    {
                        string message = String.Format(Catalog.GetString("Array (with attachment) is too long. Max size is {0} bytes."),
                                                       ComPort.MAX_BLOCK_LENGTH);
                        throw new Exception(message);
                    }

                    this.Port.Write(total_bytes, 0, total_bytes.Length);
                    System.Threading.Thread.Sleep(this.WriteBlockInterval);
                    this.State = ComPortState.Ready;
                    return total_bytes.Length;
                }
                catch(Exception ex)
                {
                    this.HandleError(ex, false);
                    return 0;
                }
            }
        }

        private byte[] AddAttachment(byte[] array)
        {
            if (string.IsNullOrEmpty(this.Attachment) == true)
                return array;

            byte[] tmp = this.encoding.GetBytes(this.attachment);
            return array.Concat(tmp).ToArray();
        }

        private string attachment = String.Empty;
        public string Attachment
        {
            get
            {
                return this.attachment;
            }

            set
            {
                lock (this)
                {
                    this.CheckDisosed();
                    this.attachment = value ?? String.Empty;
                }
            }
        }

        private byte[] WriteBuffer { get; set; } = null;
        public int WriteBlockInterval { get; set; } = 0;
    }
}
