/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.test.wysiwyg.framework;

import java.util.HashMap;
import java.util.Map;

import junit.extensions.TestSetup;
import junit.framework.Test;
import junit.framework.TestSuite;

/**
 * Prepares the WYSIWYG test suite by setting up general WYSIWYG preferences (such as enabling all editing features in
 * the editor or logging in as admin).
 * 
 * @version $Id$
 */
public class WysiwygTestSetup extends TestSetup
{
    /**
     * Create a new setup, for the passed tests.
     * 
     * @param tests the tests to decorate with this setup
     */
    public WysiwygTestSetup(Test test)
    {
        super(test);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void setUp() throws Exception
    {
        super.setUp();
        // Get the first WYSIWYG test to do the setup with its provided API.
        AbstractWysiwygTestCase firstXWikiTest = getFirstWysiwygTest(getTest());

        if (firstXWikiTest == null) {
            return;
        }

        // Set up the WYSIWYG tests using the first WYSIWYG Test case for Selenium and skin executor API.
        enableAllEditingFeatures(firstXWikiTest);
    }

    /**
     * @return the first {@link AbstractWysiwygTestCase} (in a suite) wrapped by this decorator
     */
    private AbstractWysiwygTestCase getFirstWysiwygTest(Test test)
    {
        if (test instanceof TestSuite) {
            if (((TestSuite) test).tests().hasMoreElements()) {
                // Normally this should be the first one.
                Test currentTest = ((TestSuite) test).tests().nextElement();
                if (currentTest instanceof AbstractWysiwygTestCase) {
                    return (AbstractWysiwygTestCase) currentTest;
                }
            }
        } else if (test instanceof TestSetup) {
            return getFirstWysiwygTest(((TestSetup) test).getTest());
        } else if (test instanceof AbstractWysiwygTestCase) {
            return (AbstractWysiwygTestCase) test;
        }

        return null;
    }

    /**
     * Enables all editing features so they are accessible for testing.
     * 
     * @param helperTest helper {@link AbstractWysiwygTestCase} instance whose API to use to do the setup
     */
    private void enableAllEditingFeatures(AbstractWysiwygTestCase helperTest)
    {
        // login as admin and enable editing features.
        helperTest.loginAsAdmin();
        Map<String, String> config = new HashMap<String, String>();
        config.put("wysiwyg.plugins", "submit readonly line separator embed text valign list "
            + "indent history format symbol link image " + "table macro import color justify font");
        config.put("wysiwyg.toolbar", "bold italic underline strikethrough teletype | subscript superscript | "
            + "justifyleft justifycenter justifyright justifyfull | unorderedlist orderedlist | outdent indent | "
            + "undo redo | format | fontname fontsize forecolor backcolor | hr removeformat symbol | "
            + " paste | macro:velocity");
        updateXWikiPreferences(config, helperTest);
    }

    /**
     * Updates XWiki preferences based on the given configuration object. The key in the configuration is the name of a
     * XWiki preference and the value is the new value for that preference.
     * 
     * @param config configuration object
     * @param helperTest helper {@link AbstractWysiwygTestCase} instance whose API to use to do the setup
     */
    private void updateXWikiPreferences(Map<String, String> config, AbstractWysiwygTestCase helperTest)
    {
        helperTest.open("XWiki", "XWikiPreferences", "edit", "editor=object");
        for (Map.Entry<String, String> entry : config.entrySet()) {
            String propertyId = "XWiki.XWikiPreferences_0_" + entry.getKey();
            if (!helperTest.isElementPresent(propertyId)) {
                addXWikiStringPreference(entry.getKey(), helperTest);
            }
            if (!entry.getValue().equals(helperTest.getFieldValue(propertyId))) {
                helperTest.setFieldValue(propertyId, entry.getValue());
                helperTest.clickEditSaveAndContinue();
            }
        }
    }

    /**
     * Adds a string property to the XWiki.XWikiPreferences class.
     * 
     * @param name the property name
     * @param helperTest helper {@link AbstractWysiwygTestCase} instance whose API to use to do the setup
     */
    private void addXWikiStringPreference(String name, AbstractWysiwygTestCase helperTest)
    {
        String location = helperTest.getSelenium().getLocation();
        helperTest.open("XWiki", "XWikiPreferences", "edit", "editor=class");
        helperTest.setFieldValue("propname", name);
        helperTest.getSelenium().select("proptype", "String");
        helperTest.clickEditAddProperty();
        helperTest.getSelenium().open(location);
    }
}

@@ -3194,17 +3194,17 @@
      // 
-l
+L
 ogin as 
@@ -3361,24 +3361,16 @@
 ig.put(%22
-wysiwyg.
 plugins%22
@@ -3553,21 +3553,13 @@
 ut(%22
-wysiwyg.
 tool
-b
+B
 ar%22,
@@ -3907,32 +3907,29 @@
   update
-XWikiPreferences
+Configuration
 (config,
@@ -3976,25 +3976,40 @@
 tes 
-XWiki preferences
+the WYSIWYG editor configuration
  bas
@@ -4077,16 +4077,23 @@
 ation is
+%0A     *
  the nam
@@ -4102,32 +4102,56 @@
 of a
-%0A     * XWiki preference
+ %7B@code XWiki.WysiwygEditorConfigClass%7D property
  and
@@ -4189,24 +4189,22 @@
  that pr
-eference
+operty
 .%0A     *
@@ -4384,32 +4384,29 @@
 d update
-XWikiPreferences
+Configuration
 (Map%3CStr
@@ -4502,32 +4502,35 @@
 Wiki%22, %22
-XWikiPreferences
+WysiwygEditorConfig
 %22, %22edit
@@ -4657,31 +4657,39 @@
  %22XWiki.
-XWikiPreference
+WysiwygEditorConfigClas
 s_0_%22 + 
@@ -4708,152 +4708,8 @@
 ();%0A
-            if (!helperTest.isElementPresent(propertyId)) %7B%0A                addXWikiStringPreference(entry.getKey(), helperTest);%0A            %7D%0A
     
@@ -4946,696 +4946,7 @@
    %7D
-%0A%0A    /**%0A     * Adds a string property to the XWiki.XWikiPreferences class.%0A     * %0A     * @param name the property name%0A     * @param helperTest helper %7B@link AbstractWysiwygTestCase%7D instance whose API to use to do the setup%0A     */%0A    private void addXWikiStringPreference(String name, AbstractWysiwygTestCase helperTest)%0A    %7B%0A        String location = helperTest.getSelenium().getLocation();%0A        helperTest.open(%22XWiki%22, %22XWikiPreferences%22, %22edit%22, %22editor=class%22);%0A        helperTest.setFieldValue(%22propname%22, name);%0A        helperTest.getSelenium().select(%22proptype%22, %22String%22);%0A        helperTest.clickEditAddProperty();%0A        helperTest.getSelenium().open(location);%0A    %7D
 %0A%7D%0A

Use the XWiki.WysiwygEditorConfig class/object to configure the WYSIWYG editor