////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//
// This file contains content from Ethan Brand by Nathaniel Hawthorne,
// now in the public domain.
//
////////////////////////////////////////////////////////////////////////////////

package UnitTest.Tests
{

    import UnitTest.ExtendedClasses.VellumTestCase;
    import UnitTest.Fixtures.FileRepository;
    import UnitTest.Fixtures.TestConfig;

    import flashx.textLayout.conversion.ConversionType;
    import flashx.textLayout.conversion.TextConverter;
    import flashx.textLayout.edit.TextScrap;
    import flashx.textLayout.elements.FlowElement;
    import flashx.textLayout.elements.TextFlow;
    import flashx.textLayout.formats.ITextLayoutFormat;
    import flashx.textLayout.formats.TextLayoutFormat;

    import org.flexunit.asserts.assertEquals;
    import org.flexunit.asserts.assertNotNull;
    import org.flexunit.asserts.assertTrue;

    public class FLEX_34807_Test extends VellumTestCase
    {
        private static const PASTED_TEXT:String = '|Hey world!|';
        private static const PASTED_HTML:String = '<span style="fontSize:12">|<i>Hey<b> world</b>!</i>|</span>';
        private static const PASTE:TextScrap = new TextScrap(TextConverter.importToFlow(PASTED_HTML, TextConverter.TEXT_FIELD_HTML_FORMAT));

        private static var PASTE_CHAR_STYLES:Array = [];

        private var sourceAsPlainText:String;
        private var leftBefore:ITextLayoutFormat;
        private var rightBefore:ITextLayoutFormat;
        private var leftAfter:ITextLayoutFormat;
        private var rightAfter:ITextLayoutFormat;
        private var initialTextLength:Number = NaN;

        public function FLEX_34807_Test()
        {
            //	super(methodName, testID, testConfig, testCaseXML);
            super("", "FLEX_34807_Test", TestConfig.getInstance());

            metaData = {};

            TestData.fileName = "HtmlTest.xml";
        }

        [BeforeClass]
        public static function setUpClass():void
        {
            FileRepository.readFile(TestConfig.getInstance().baseURL, "../../test/testFiles/markup/tlf/HtmlTest.xml");
            analyseStylesOfPastedText();
        }

        private static function analyseStylesOfPastedText():void
        {
            for(var i:int = 0; i < PASTED_TEXT.length; i++)
            {
                PASTE_CHAR_STYLES.push(getFormatOfCharFromFlow(i, PASTE.textFlow));
            }
        }

        [Before]
        override public function setUpTest():void
        {
            super.setUpTest();

            if(!sourceAsPlainText)
                sourceAsPlainText = TextConverter.export(testApp.getTextFlow(), TextConverter.PLAIN_TEXT_FORMAT, ConversionType.STRING_TYPE) as String;

            if(isNaN(initialTextLength))
                initialTextLength = SelManager.textFlow.textLength;
        }

        [After]
        public override function tearDownTest():void
        {
            super.tearDownTest();
        }

        [Test]
        public function paste_in_beginning():void
        {
            //given
            recordTextFormatsBeforeOperation(0);

            //when
            SelManager.selectFirstPosition();
            SelManager.pasteTextScrap(PASTE);

            //then
            assertAdjacentTextFormatsNotAltered(0);
            assertFormattingOfPastedTextNotAltered(0);
            assertTextPastedCorrectlyAndExistingTextNotChanged(0);
        }

        [Test]
        public function paste_in_first_paragraph():void
        {
            //given
            const PASTE_POSITION:int = 5; //after "There"
            recordTextFormatsBeforeOperation(PASTE_POSITION);

            //when
            SelManager.selectRange(PASTE_POSITION, PASTE_POSITION);
            SelManager.pasteTextScrap(PASTE);

            //then
            assertAdjacentTextFormatsNotAltered(PASTE_POSITION);
            assertFormattingOfPastedTextNotAltered(PASTE_POSITION);
            assertTextPastedCorrectlyAndExistingTextNotChanged(PASTE_POSITION);
        }

        [Test]
        public function paste_in_first_paragraph_in_middle_of_bold_section():void
        {
            //given
            const PASTE_POSITION:int = 16;
            recordTextFormatsBeforeOperation(PASTE_POSITION);

            //when
            SelManager.selectRange(PASTE_POSITION, PASTE_POSITION);
            SelManager.pasteTextScrap(PASTE);

            //then
            assertAdjacentTextFormatsNotAltered(PASTE_POSITION);
            assertFormattingOfPastedTextNotAltered(PASTE_POSITION);
            assertTextPastedCorrectlyAndExistingTextNotChanged(PASTE_POSITION);
        }

        [Test]
        public function paste_in_second_paragraph():void
        {
            //given
            const PASTE_POSITION:int = 170;
            recordTextFormatsBeforeOperation(PASTE_POSITION);

            //when
            SelManager.selectRange(PASTE_POSITION, PASTE_POSITION);
            SelManager.pasteTextScrap(PASTE);

            //then
            assertAdjacentTextFormatsNotAltered(PASTE_POSITION);
            assertFormattingOfPastedTextNotAltered(PASTE_POSITION);
            assertTextPastedCorrectlyAndExistingTextNotChanged(PASTE_POSITION);
        }

        [Test]
        public function paste_at_end():void
        {
            //given
            const PASTE_POSITION:int = SelManager.textFlow.textLength - 1;
            recordTextFormatsBeforeOperation(PASTE_POSITION);

            //when
            SelManager.selectRange(PASTE_POSITION, PASTE_POSITION);
            SelManager.pasteTextScrap(PASTE);

            //then
            assertAdjacentTextFormatsNotAltered(PASTE_POSITION);
            assertFormattingOfPastedTextNotAltered(PASTE_POSITION);
            assertTextPastedCorrectlyAndExistingTextNotChanged(PASTE_POSITION);
        }

        private function assertFormattingOfPastedTextNotAltered(pastePosition:int):void
        {
            for(var i:int = 0; i < PASTED_TEXT.length; i++)
            {
                var formatOfPastedChar:ITextLayoutFormat = getFormatOfCharAt(pastePosition + i);
                assertTrue("The style of the pasted text has been altered!", TextLayoutFormat.isEqual(PASTE_CHAR_STYLES[i], formatOfPastedChar));
            }
        }

        private function assertAdjacentTextFormatsNotAltered(pastePosition:int):void
        {
            recordTextFormatsAfterOperation(pastePosition);
            assertAdjacentTextFormatsArePreserved(pastePosition);
        }

        private function assertAdjacentTextFormatsArePreserved(pastePosition:int):void
        {
            if(pastePosition)
            {
                assertNotNull("Couldn't manage to find the format of the character to the left of the pasted text, before the paste operation!", leftBefore);
                assertNotNull("Couldn't manage to find the format of the character to the left of the pasted text, after the paste operation!", leftAfter);
                assertTrue("The style of the original text has been altered! (left)", TextLayoutFormat.isEqual(leftBefore, leftAfter));
            }

            if(pastePosition < initialTextLength - 1)
            {
                assertNotNull("Couldn't manage to find the format of the character to the right of the pasted text, before the paste operation!", rightBefore);
                assertNotNull("Couldn't manage to find the format of the character to the right of the pasted text, after the paste operation!", rightAfter);
                assertTrue("The style of the original text has been altered! (right)", TextLayoutFormat.isEqual(rightBefore, rightAfter));
            }
        }

        private function recordTextFormatsBeforeOperation(pastePosition:int):void
        {
            leftBefore = pastePosition ? getFormatOfCharAt(pastePosition - 1) : null;
            rightBefore = pastePosition < initialTextLength - 1 ?  getFormatOfCharAt(pastePosition + 1) : null;
        }

        private function recordTextFormatsAfterOperation(pastePosition:int):void
        {
            leftAfter = pastePosition ? getFormatOfCharAt(pastePosition - 1) : null;
            rightAfter = pastePosition < initialTextLength - 1 ? getFormatOfCharAt(pastePosition + 1 + PASTED_TEXT.length) : null;
        }

        private function getFormatOfCharAt(position:int, flow:TextFlow = null):ITextLayoutFormat
        {
            return getFormatOfCharFromFlow(position, flow || SelManager.textFlow);
        }

        private static function getFormatOfCharFromFlow(position:int, flow:TextFlow):ITextLayoutFormat
        {
            const elementAtPosition:FlowElement = flow.findLeaf(position);
            return elementAtPosition ? elementAtPosition.format : null;
        }

        private function assertTextPastedCorrectlyAndExistingTextNotChanged(pastePosition:int):void
        {
            const currentSourceAsPlainText:String = TextConverter.export(testApp.getTextFlow(), TextConverter.PLAIN_TEXT_FORMAT, ConversionType.STRING_TYPE) as String;
            assertEquals("Not all the pasted content appears in the new TextFlow!", sourceAsPlainText.substr(0, pastePosition) + PASTED_TEXT + "\n" + sourceAsPlainText.substr(pastePosition), currentSourceAsPlainText);
        }
    }
}