#region Disclaimer / License

// Copyright (C) 2012, Jackie Ng
// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

// Original code by Michael Potter, made available under Public Domain
//
// http://www.codeproject.com/Articles/6943/A-Generic-Reusable-Diff-Algorithm-in-C-II/

#endregion Disclaimer / License

using OSGeo.MapGuide.MaestroAPI.Resource.Comparison;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Maestro.Editors.Diff
{
    /// <summary>
    /// Displays a visual comparison of two bodies of text
    /// </summary>
    public partial class TextDiffView : Form
    {
        /// <summary>
        /// Initializes a new instance
        /// </summary>
        public TextDiffView()
        {
            InitializeComponent();
        }

        private const string NumFormat = "00000";

        /// <summary>
        /// Initializes a new instance
        /// </summary>
        public TextDiffView(TextFileDiffList source, TextFileDiffList destination, List<DiffResultSpan> DiffLines, double seconds)
            : this()
        {
            int cnt = 1;
            int i;

            foreach (DiffResultSpan drs in DiffLines)
            {
                switch (drs.Status)
                {
                    case DiffResultSpanStatus.DeleteSource:
                        for (i = 0; i < drs.Length; i++)
                        {
                            var lvi = new ListViewItem(cnt.ToString(NumFormat));
                            lvi.UseItemStyleForSubItems = false;
                            var sline = lvi.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            sline.BackColor = Color.Red;
                            var dlineNo = lvi.SubItems.Add(cnt.ToString(NumFormat));
                            var dline = lvi.SubItems.Add(string.Empty);
                            dline.BackColor = Color.LightGray;
                            lvSource.Items.Add(lvi);
                            cnt++;
                        }

                        break;

                    case DiffResultSpanStatus.NoChange:
                        for (i = 0; i < drs.Length; i++)
                        {
                            var lvi = new ListViewItem(cnt.ToString(NumFormat));
                            lvi.UseItemStyleForSubItems = false;
                            var sline = lvi.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            sline.BackColor = Color.White;
                            var dlineNo = lvi.SubItems.Add(cnt.ToString(NumFormat));
                            var dline = lvi.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);
                            dline.BackColor = Color.White;
                            lvSource.Items.Add(lvi);
                            cnt++;
                        }

                        break;

                    case DiffResultSpanStatus.AddDestination:
                        for (i = 0; i < drs.Length; i++)
                        {
                            var lvi = new ListViewItem(cnt.ToString(NumFormat));
                            lvi.UseItemStyleForSubItems = false;
                            var sline = lvi.SubItems.Add(string.Empty);
                            sline.BackColor = Color.LightGray;
                            var dlineNo = lvi.SubItems.Add(cnt.ToString(NumFormat));
                            var dline = lvi.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);
                            dline.BackColor = Color.LightGreen;
                            lvSource.Items.Add(lvi);
                            cnt++;
                        }

                        break;

                    case DiffResultSpanStatus.Replace:
                        for (i = 0; i < drs.Length; i++)
                        {
                            var lvi = new ListViewItem(cnt.ToString(NumFormat));
                            lvi.UseItemStyleForSubItems = false;
                            var sline = lvi.SubItems.Add(((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line);
                            sline.BackColor = Color.Red;
                            var dlineNo = lvi.SubItems.Add(cnt.ToString(NumFormat));
                            var dline = lvi.SubItems.Add(((TextLine)destination.GetByIndex(drs.DestIndex + i)).Line);
                            dline.BackColor = Color.LightGreen;
                            lvSource.Items.Add(lvi);
                            cnt++;
                        }

                        break;
                }
            }
        }

        /// <summary>
        /// Sets the labels of the left and right sides of the comparison
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        public void SetLabels(string left, string right)
        {
            lblLeft.Text = left;
            lblRight.Text = right;
        }

        private void lvSource_Resize(object sender, System.EventArgs e)
        {
            try
            {
                lvSource.SuspendLayout();
                int width = (int)((lvSource.Width - lvSource.Columns[0].Width - lvSource.Columns[2].Width) / 2);

                lvSource.Columns[1].Width = width;
                lvSource.Columns[3].Width = width;
            }
            finally
            {
                lvSource.ResumeLayout();
            }
        }

        private void Results_Resize(object sender, System.EventArgs e)
        {
            int w = this.ClientRectangle.Width / 2;
            lblRight.Location = new Point(w + 1, lblRight.Location.Y);
        }

        private void Results_Load(object sender, System.EventArgs e)
        {
            lvSource_Resize(sender, e);
        }
    }
}