// <copyright file="Signature.cs" company="Scriptel Corporation">
//      Copyright 2014 - Scriptel Corporation
// </copyright>
namespace EasyScriptAPI
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// This class represents a parsed signature from a Scriptel ScripTouch EasyScript product.
    /// </summary>
    public class Signature
    {
        /// <summary>
        /// The version of the protocol used to generate this signature.
        /// </summary>
        private string protocolVersion;

        /// <summary>
        /// The model number of the device used to generate this signature.
        /// </summary>
        private string model;

        /// <summary>
        /// The firmware version of the device used to generate this signature.
        /// </summary>
        private string version;

        /// <summary>
        /// A list of the strokes that make up the signature.
        /// </summary>
        private List<List<Coordinate>> strokes;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="Signature"/> class.
        /// </summary>
        /// <param name="protocolVersion">Protocol Version of the decoded string</param>
        /// <param name="model">Model number used to generate the string</param>
        /// <param name="version">Firmware version used to generate the string</param>
        /// <param name="strokes">List of strokes containing coordinates</param>
        public Signature(string protocolVersion, string model, string version, List<List<Coordinate>> strokes)
        {
            this.protocolVersion = protocolVersion;
            this.model = model;
            this.version = version;
            this.strokes = strokes;
        }

        /// <summary>
        /// Returns a human readable string representation of this object.
        /// </summary>
        /// <returns>Human readable string representation of this object.</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            string newline = Environment.NewLine;
            sb.Append("Scriptel EasyScript Signature:\n");
            sb.Append("   Protocol Version: ").Append(this.protocolVersion).Append(newline);
            sb.Append("       Device Model: ").Append(this.model).Append(newline);
            sb.Append("   Firmware Version: ").Append(this.version).Append(newline);
            sb.Append("            Strokes: ").Append(Convert.ToString(this.strokes.Count)).Append(newline);
            for (int x = 0; x < this.strokes.Count; x++)
            {
                sb.Append("   Stroke ").Append(x).Append(":").Append(newline);
                List<Coordinate> strokeList = this.strokes[x];
                for (int strokeCount = 0; strokeCount < strokeList.Count; ++strokeCount)
                {
                    Coordinate c = (Coordinate)strokeList[strokeCount];
                    sb.Append("      ").Append(c).Append(newline);
                }

                sb.Append(newline);
            }

            return sb.ToString();
        }
    
        /// <summary>
        /// Gets the protocol version used to generate the EasyScript string
        /// </summary>
        /// <returns>protocol version used to generate the EasyScript string</returns>
        public string GetProtocolVersion()
        {
            return this.protocolVersion;
        }

        /// <summary>
        /// The model number of the device used to generate the EasyScript string
        /// </summary>
        /// <returns>model number of the device used to generate the EasyScript string</returns>
        public string GetModel()
        {
            return this.model;
        }

        /// <summary>
        /// The firmware version of the device used to create the string
        /// </summary>
        /// <returns>firmware version of the device used to create the string</returns>
        public string GetVersion()
        {
            return this.version;
        }

        /// <summary>
        /// Returns list of strokes, each containing a list of coordinates that make up the signature.
        /// </summary>
        /// <returns>list of strokes, each containing a list of coordinates that make up the signature.</returns>
        public List<List<Coordinate>> GetStrokes()
        {
            return this.strokes;
        }

        /// <summary>
        /// This method gets the bounding box of this signature.
        /// </summary>
        /// <returns>A bounding box around this signature.</returns>
        public SignatureBounds GetBounds()
        {
            SignatureBounds bounds = new SignatureBounds();

            bounds.X1 = Double.MaxValue;
            bounds.Y1 = Double.MaxValue;
            bounds.X2 = -1;
            bounds.Y2 = -1;

            for (int i = 0; i < strokes.Count; i++)
            {
                for (int j = 0; j < strokes[i].Count; j++)
                {
                    Coordinate c = strokes[i][j];

                    bounds.X1 = (c.X < bounds.X1) ? c.X : bounds.X1;
                    bounds.X2 = (c.X > bounds.X2) ? c.X : bounds.X2;

                    bounds.Y1 = (c.Y < bounds.Y1) ? c.Y : bounds.Y1;
                    bounds.Y2 = (c.Y > bounds.Y2) ? c.Y : bounds.Y2;
                }
            }

            bounds.Width = bounds.X2 - bounds.X1;
            bounds.Height = bounds.Y2 - bounds.Y1;

            return bounds;
        }

        /// <summary>
        /// This method crops all of the coordinates such that they fit into the width and
        /// height of the minimum bounding box for the signature.
        /// </summary>
        public void Crop()
        {
            SignatureBounds bounds = GetBounds();
            for (int i = 0; i < strokes.Count; i++)
            {
                for (int j = 0; j < strokes[i].Count; j++)
                {
                    Coordinate c = strokes[i][j];
                    c.X -= bounds.X1;
                    c.Y -= bounds.Y1;
                }
            }
        }
    }
}
