using NUnit.Framework;
using NcProgramManager;

namespace NcProgramManager.Tests.Unit
{
    [TestFixture]
    public class FanucProgramParsingTests
    {
        private const string SimpleProgram =
            "\nO1234(COMMENT)\n" +
            "G0 X0 Y0\n" +
            "M30\n" +
            "%";

        private const string ThreeFileInput =
            "program:{\n" +
            "\nO1234(COMMENT)\n" +
            "G0 X0 Y0\n" +
            "M30\n" +
            "%\n" +
            "}\n" +
            "tooloffsetdata:{\n" +
            "TOOL_DATA_LINE1\n" +
            "}\n" +
            "workzerooffset:{\n" +
            "WORK_ZERO_LINE1\n" +
            "}\n";

        [Test]
        public void Constructor_OldFormat_ProgramFieldSet()
        {
            var p = new FanucProgram(SimpleProgram);

            Assert.That(p.Program, Is.Not.Null);
            Assert.That(p.ToolOffsetData, Is.Null);
            Assert.That(p.WorkZeroOffsetData, Is.Null);
        }

        [Test]
        public void Constructor_ThreeFileFormat_AllSectionsSet()
        {
            var p = new FanucProgram(ThreeFileInput);

            Assert.That(p.Program, Is.Not.Null);
            Assert.That(p.ToolOffsetData, Is.Not.Null);
            Assert.That(p.WorkZeroOffsetData, Is.Not.Null);
        }

        [Test]
        public void Constructor_ThreeFileFormat_ToolOffsetDataContent()
        {
            var p = new FanucProgram(ThreeFileInput);

            Assert.That(p.ToolOffsetData, Does.Contain("TOOL_DATA_LINE1"));
        }

        [Test]
        public void Constructor_ThreeFileFormat_WorkZeroOffsetDataContent()
        {
            var p = new FanucProgram(ThreeFileInput);

            Assert.That(p.WorkZeroOffsetData, Does.Contain("WORK_ZERO_LINE1"));
        }

        [Test]
        public void GetProgramTitle_StandardProgram_ReturnsO1234()
        {
            var p = new FanucProgram(SimpleProgram);

            string title = p.GetProgramTitle();

            Assert.That(title, Is.EqualTo("O1234"));
        }

        [Test]
        public void GetProgramTitle_Static_ReturnsTitle()
        {
            string title = FanucProgram.GetProgramTitle("\nO5678\nG0\n%");

            Assert.That(title, Is.EqualTo("O5678"));
        }

        [Test]
        public void GetProgramComment_ProgramWithComment_ReturnsComment()
        {
            var p = new FanucProgram(SimpleProgram);

            string comment = p.GetProgramComment();

            Assert.That(comment, Is.EqualTo("COMMENT"));
        }

        [Test]
        public void GetProgramComment_ProgramWithoutComment_ReturnsEmpty()
        {
            var p = new FanucProgram("\nO1234\nG0 X0\nM30\n%");

            string comment = p.GetProgramComment();

            Assert.That(comment, Is.EqualTo(""));
        }

        [Test]
        public void ChangeComment_ReplaceExistingComment_CommentUpdated()
        {
            var p = new FanucProgram(SimpleProgram);

            p.ChangeComment("NEW_COMMENT");

            Assert.That(p.GetProgramComment(), Is.EqualTo("NEW_COMMENT"));
        }

        [Test]
        public void ChangeComment_NoExistingComment_CommentInserted()
        {
            var p = new FanucProgram("\nO1234\nG0 X0\nM30\n%");

            p.ChangeComment("INSERTED");

            Assert.That(p.GetProgramComment(), Is.EqualTo("INSERTED"));
        }

        [Test]
        public void Standardize_LeadingPercent_Removed()
        {
            var p = new FanucProgram("%\nO1234\nG0\n%");

            Assert.That(p.Program, Does.Not.StartWith("%"));
        }

        [Test]
        public void Standardize_AngleBracketTitle_ConvertedToPlain()
        {
            var p = new FanucProgram("\n<O1234>\nG0\n%");

            Assert.That(p.Program, Does.Contain("O1234"));
            Assert.That(p.Program, Does.Not.Contain("<O1234>"));
        }

        [Test]
        public void ToString_ThreeFileFormat_ContainsAllSections()
        {
            var p = new FanucProgram(ThreeFileInput);

            string output = p.ToString();

            Assert.That(output, Does.Contain("program:{"));
            Assert.That(output, Does.Contain("tooloffsetdata:{"));
            Assert.That(output, Does.Contain("workzerooffset:{"));
        }

        [Test]
        public void ToString_ProgramContent_RoundTrips()
        {
            var p = new FanucProgram(ThreeFileInput);

            string output = p.ToString();
            var p2 = new FanucProgram(output);

            Assert.That(p2.GetProgramTitle(), Is.EqualTo(p.GetProgramTitle()));
            Assert.That(p2.ToolOffsetData, Does.Contain("TOOL_DATA_LINE1"));
            Assert.That(p2.WorkZeroOffsetData, Does.Contain("WORK_ZERO_LINE1"));
        }

        [Test]
        public void SetValue_ToolOffsetData_ValueStored()
        {
            var p = new FanucProgram(SimpleProgram);

            p.setValue("TOOL_DATA\n%", FanucProgram.FILE_TYPE.TOOL_OFFEST_DATA);

            Assert.That(p.ToolOffsetData, Does.Contain("TOOL_DATA"));
        }

        [Test]
        public void SetValue_WorkZeroOffset_ValueStored()
        {
            var p = new FanucProgram(SimpleProgram);

            p.setValue("WORK_DATA\n%", FanucProgram.FILE_TYPE.WORK_ZERO_OFFSET);

            Assert.That(p.WorkZeroOffsetData, Does.Contain("WORK_DATA"));
        }
    }
}
