/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.ui.struts2.editor;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.util.RollerConstants;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.pojos.CustomTemplateRendition;
import org.apache.roller.weblogger.pojos.TemplateRendition.RenditionType;
import org.apache.roller.weblogger.pojos.TemplateRendition.TemplateLanguage;
import org.apache.roller.weblogger.pojos.ThemeTemplate.ComponentType;
import org.apache.roller.weblogger.pojos.WeblogTemplate;
import org.apache.roller.weblogger.pojos.WeblogTheme;
import org.apache.roller.weblogger.ui.struts2.util.UIAction;
import org.apache.struts2.convention.annotation.AllowedMethods;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
 * Templates listing page.
 */
// TODO: make this work @AllowedMethods({"execute","add"})
public class Templates extends UIAction {

    private static Log log = LogFactory.getLog(Templates.class);

    // list of templates to display
    private List<WeblogTemplate> templates = Collections.emptyList();

    // list of template action types user is allowed to create
    private Map<ComponentType, String> availableActions = Collections.emptyMap();

    // name and action of new template if we are adding a template
    private String newTmplName = null;
    private ComponentType newTmplAction = null;

    public Templates() {
        this.actionName = "templates";
        this.desiredMenu = "editor";
        this.pageTitle = "pagesForm.title";
    }

    @Override
    public String execute() {

        // query for templates list
        try {

            // get current list of templates, minus custom stylesheet
            List<WeblogTemplate> raw = WebloggerFactory.getWeblogger()
                .getWeblogManager().getTemplates(getActionWeblog());
            List<WeblogTemplate> pages = new ArrayList<WeblogTemplate>();
            pages.addAll(raw);

            // Remove style sheet from list so not to show when theme is
            // selected in shared theme mode
            if (getActionWeblog().getTheme().getStylesheet() != null) {
                pages.remove(WebloggerFactory.getWeblogger().getWeblogManager()
                    .getTemplateByLink(getActionWeblog(), getActionWeblog().getTheme().getStylesheet().getLink()));
            }
            setTemplates(pages);

            // build list of action types that may be added
            Map<ComponentType, String> actionsMap = new EnumMap<ComponentType, String>(ComponentType.class);
            addComponentTypeToMap(actionsMap, ComponentType.CUSTOM);

            if (WeblogTheme.CUSTOM.equals(getActionWeblog().getEditorTheme())) {

                // if the weblog is using a custom theme then determine which
                // action templates are still available to be created
                addComponentTypeToMap(actionsMap, ComponentType.PERMALINK);
                addComponentTypeToMap(actionsMap, ComponentType.SEARCH);
                addComponentTypeToMap(actionsMap, ComponentType.WEBLOG);
                addComponentTypeToMap(actionsMap, ComponentType.TAGSINDEX);

                for (WeblogTemplate tmpPage : getTemplates()) {
                    if (!ComponentType.CUSTOM.equals(tmpPage.getAction())) {
                        actionsMap.remove(tmpPage.getAction());
                    }
                }
            } else {
                // Make sure we have an option for the default web page
                addComponentTypeToMap(actionsMap, ComponentType.WEBLOG);
                if (getNewTmplAction() == null) {
                    setNewTmplAction(ComponentType.WEBLOG);
                }
                for (WeblogTemplate tmpPage : getTemplates()) {
                    if (ComponentType.WEBLOG.equals(tmpPage.getAction())) {
                        actionsMap.remove(ComponentType.WEBLOG);
                        setNewTmplAction(null);
                        break;
                    }
                }
            }
            setAvailableActions(actionsMap);

        } catch (WebloggerException ex) {
            log.error("Error getting templates for weblog - "
                + getActionWeblog().getHandle(), ex);
            addError("Error getting template list - check Roller logs");
        }

        return LIST;
    }

    private void addComponentTypeToMap(Map<ComponentType, String> map, ComponentType component) {
        map.put(component, component.getReadableName());
    }

    /**
     * Save a new template.
     */
    public String add() {

        // validation
        myValidate();

        if (!hasActionErrors()) {
            try {

                WeblogTemplate newTemplate = new WeblogTemplate();
                newTemplate.setWeblog(getActionWeblog());
                newTemplate.setAction(getNewTmplAction());
                newTemplate.setName(getNewTmplName());
                newTemplate.setHidden(false);
                newTemplate.setNavbar(false);
                newTemplate.setLastModified(new Date());

                if (ComponentType.CUSTOM.equals(getNewTmplAction())) {
                    newTemplate.setLink(getNewTmplName());
                }

                // Make sure we have always have a Weblog main page. Stops
                // deleting main page in custom theme mode also.
                if (ComponentType.WEBLOG.equals(getNewTmplAction())) {
                    newTemplate.setName(WeblogTemplate.DEFAULT_PAGE);
                }

                // save the new Template
                WebloggerFactory.getWeblogger().getWeblogManager().saveTemplate(newTemplate);

                // Create weblog template renditions for available types.
                CustomTemplateRendition standardRendition =
                    new CustomTemplateRendition( newTemplate, RenditionType.STANDARD);
                standardRendition.setTemplate(getText("pageForm.newTemplateContent"));
                standardRendition.setTemplateLanguage(TemplateLanguage.VELOCITY);
                WebloggerFactory.getWeblogger().getWeblogManager().saveTemplateRendition(standardRendition);

                /* TODO: need a way for user to specify dual or single template via UI
                CustomTemplateRendition mobileRendition = new CustomTemplateRendition(
                        newTemplate.getId(), RenditionType.MOBILE);
                mobileRendition.setTemplate(newTemplate.getContents());
                mobileRendition.setTemplateLanguage(TemplateLanguage.VELOCITY);
                WebloggerFactory.getWeblogger().getWeblogManager()
                        .saveTemplateRendition(mobileRendition);
                */

                // if this person happened to create a Weblog template from
                // scratch then make sure and set the defaultPageId.
                if (WeblogTemplate.DEFAULT_PAGE.equals(newTemplate.getName())) {
                    WebloggerFactory.getWeblogger().getWeblogManager().saveWeblog(getActionWeblog());
                }

                // flush results to db
                WebloggerFactory.getWeblogger().flush();

                // reset form fields
                setNewTmplName(null);
                setNewTmplAction(null);

            } catch (WebloggerException ex) {
                log.error("Error adding new template for weblog - " + getActionWeblog().getHandle(), ex);
                addError("Error adding new template - check Roller logs");
            }
        }

        return execute();
    }

    // validation when adding a new template
    private void myValidate() {

        // make sure name is non-null and within proper size
        if (StringUtils.isEmpty(getNewTmplName())) {
            addError("Template.error.nameNull");
        } else if (getNewTmplName().length() > RollerConstants.TEXTWIDTH_255) {
            addError("Template.error.nameSize");
        }

        // make sure action is a valid
        if (getNewTmplAction() == null) {
            addError("Template.error.actionNull");
        }

        // check if template by that name already exists
        try {
            WeblogTemplate existingPage = WebloggerFactory.getWeblogger().getWeblogManager()
                .getTemplateByName(getActionWeblog(), getNewTmplName());
            if (existingPage != null) {
                addError("pagesForm.error.alreadyExists", getNewTmplName());
            }
        } catch (WebloggerException ex) {
            log.error("Error checking for existing template", ex);
        }

    }

    /**
     * Checks if is custom theme.
     *
     * @return true, if is custom theme
     */
    public boolean isCustomTheme() {
        return (WeblogTheme.CUSTOM.equals(getActionWeblog().getEditorTheme()));
    }

    public List<WeblogTemplate> getTemplates() {
        return templates;
    }

    public void setTemplates(List<WeblogTemplate> templates) {
        this.templates = templates;
    }

    public Map<ComponentType, String> getAvailableActions() {
        return availableActions;
    }

    public void setAvailableActions(Map<ComponentType, String> availableActions) {
        this.availableActions = availableActions;
    }

    public String getNewTmplName() {
        return newTmplName;
    }

    public void setNewTmplName(String newTmplName) {
        this.newTmplName = newTmplName;
    }

    public ComponentType getNewTmplAction() {
        return newTmplAction;
    }

    public void setNewTmplAction(ComponentType newTmplAction) {
        this.newTmplAction = newTmplAction;
    }

}
