/*
 * 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.
 */
package org.apache.struts2.components;

import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.views.annotations.StrutsTagAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * FormButton.
 */
public abstract class FormButton extends ClosingUIBean {

    private static final String BUTTON_TYPE_INPUT = "input";
    private static final String BUTTON_TYPE_BUTTON = "button";
    private static final String BUTTON_TYPE_IMAGE = "image";

    protected String action;
    protected String method;
    protected String type;

    public FormButton(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
        super(stack, request, response);
    }

    //public void evaluateParams() {
    public void evaluateExtraParams() {
        super.evaluateExtraParams();

        String submitType = BUTTON_TYPE_INPUT;
        if (type != null && (BUTTON_TYPE_BUTTON.equalsIgnoreCase(type) || (supportsImageType() && BUTTON_TYPE_IMAGE.equalsIgnoreCase(type)))) {
            submitType = type;
        }

        //super.evaluateParams();

        addParameter("type", submitType);

        if (!BUTTON_TYPE_INPUT.equals(submitType) && (label == null)) {
            addParameter("label", getParameters().get("nameValue"));
        }

        if (action != null || method != null) {
            String name;

            if (action != null) {
                ActionMapping mapping = new ActionMapping();
                mapping.setName(findString(action));
                if (method != null) {
                    mapping.setMethod(findString(method));
                }
                mapping.setExtension("");
                name = "action:" + actionMapper.getUriFromActionMapping(mapping);
            } else {
                name = "method:" + findString(method);
            }

            addParameter("name", name);
        }

    }

    /**
     * Override UIBean's implementation, such that component Html id is determined
     * in the following order :-
     * <ol>
     *   <li>This component id attribute</li>
     *   <li>[containing_form_id]_[this_component_name]</li>
     *   <li>[containing_form_id]_[this_component_action]_[this_component_method]</li>
     *   <li>[containing_form_id]_[this_component_method]</li>
     *   <li>[this_component_name]</li>
     *   <li>[this_component_action]_[this_component_method]</li>
     *   <li>[this_component_method]</li>
     *   <li>[an increasing sequential number unique to the form starting with 0]</li>
     * </ol>
     */
    protected void populateComponentHtmlId(Form form) {
        String _tmp_id = "";
        if (id != null) {
            // this check is needed for backwards compatibility with 2.1.x
            _tmp_id = findString(id);
        } else {
            if (form != null && form.getParameters().get("id") != null) {
                _tmp_id = _tmp_id + form.getParameters().get("id").toString() + "_";
            }
            if (name != null) {
                _tmp_id = _tmp_id + escape(name);
            } else if (action != null || method != null) {
                if (action != null) {
                    _tmp_id = _tmp_id + escape(action);
                }
                if (method != null) {
                    _tmp_id = _tmp_id + "_" + escape(method);
                }
            } else {
                // if form is null, this component is used, without a form, i guess
                // there's not much we could do then.
                if (form != null) {
                    _tmp_id = _tmp_id + form.getSequence();
                }
            }
        }
        addParameter("id", _tmp_id);
        addParameter("escapedId", escape(_tmp_id));
    }

    /**
     * Indicate whether the concrete button supports the type "image".
     *
     * @return <tt>true</tt> if type image is supported.
     */
    protected abstract boolean supportsImageType();

    @Inject
    public void setActionMapper(ActionMapper mapper) {
        this.actionMapper = mapper;
    }

    @StrutsTagAttribute(description = "Set action attribute.")
    public void setAction(String action) {
        this.action = action;
    }

    @StrutsTagAttribute(description = "Set method attribute.")
    public void setMethod(String method) {
        this.method = method;
    }


    @StrutsTagAttribute(description = "The type of submit to use. Valid values are <i>input</i>, " +
        "<i>button</i> and <i>image</i>.", defaultValue = "input")
    public void setType(String type) {
        this.type = type;
    }
}
