/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed 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.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.behaviors.dojo;

import org.apache.wicket.Component;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;

/**
 * This class renders the drag and drop ability from the DojoToolKit to a component.

 * It is used for all tags which can be part of the Dojo-dnd. The handles, items and the Source.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class DnDBehavior
    extends AbstractDojoBehavior
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Enum used to set the Type of Drag and Drop this Behavior should render.
     */
    public enum BehaviorType
    {
        /** Render a item. */
        ITEM,
        /** Render a source. */
        SOURCE;
    }

    /**
     * This instance variable stores what kind should be rendered.
     */
    private final BehaviorType type;

    /**
     * this instance variable stores a javascript which will be
     * executed after the drag and drop. It is only used in
     * case of BehaviorType.SOURCE
     */
    private String appendJavaScript;

    /**
     * Type.
     */
    private CharSequence dndType = "eFapsdnd";

    /**
     * Constructor setting the Type of the DnDBehavior. Instead of
     * using this constructor it can be used on e of the
     * static methods.

     * {@link #getHandleBehavior()}

{@link #getItemBehavior()}

     * {@link #getSourceBehavior()}

     *
     * @param _type BehaviorType of this DnDBehavior
     */
    public DnDBehavior(final BehaviorType _type)
    {
        this.type = _type;
    }

    /**
     * Constructor setting the type and dendtype.
     *
     * @param _type BehaviorType of this DnDBehavior
     * @param _dndType dndType
     */
    public DnDBehavior(final BehaviorType _type,
                       final String _dndType)
    {
        this.type = _type;
        this.dndType = _dndType;
    }

    /**
     * The tag of the component must be altered, so that the dojo dnd will be rendered.
     *
     * @see org.apache.wicket.behavior.AbstractBehavior#onComponentTag(org.apache.wicket.Component,
     *      org.apache.wicket.markup.ComponentTag)
     * @param _component Component
     * @param _tag tag to edit
     */
    @Override
    public void onComponentTag(final Component _component,
                               final ComponentTag _tag)
    {
        super.onComponentTag(_component, _tag);

        if (this.type == DnDBehavior.BehaviorType.ITEM) {
            String value = "dojoDndItem ";
            if (_tag.getAttribute("class") != null) {
                value += _tag.getAttribute("class");
            }
            _tag.put("dndType", this.dndType);
            _tag.put("class", value);
        }
    }

    /**
     * Add the javascriupt to the head of the webpage.
     *
     * @see org.efaps.ui.wicket.behaviors.dojo.AbstractDojoBehavior#renderHead(
     * org.apache.wicket.markup.html.IHeaderResponse)
     *
     * @param _component component the header will be rendered for
     * @param _response rseponse
     */
    @Override
    public void renderHead(final Component _component,
                           final IHeaderResponse _response)
    {
        super.renderHead(_component, _response);
        _response.render(RequireHeaderItem.forClasses(DojoClasses.DnDSource, DojoClasses.parser));

        if (this.type == DnDBehavior.BehaviorType.SOURCE) {
            final StringBuilder js = new StringBuilder()
                .append("var nSrc = new dojo.dnd.Source(dom.byId('").append(_component.getMarkupId(true)).append("'),")
                .append("{ accept: ['" + this.dndType + "']});")
                .append(" aspect.after(nSrc,\"onDrop\", function(){\n")
                .append(this.appendJavaScript)
                .append("\n});");
            _response.render(OnDojoReadyHeaderItem.forScript(DojoWrapper.require(js, DojoClasses.aspect,
                            DojoClasses.dom, DojoClasses.DnDSource)));
        }
    }

    /**
     * This is the getter method for the instance variable {@link #appendJavaScript}.
     *
     * @return value of instance variable {@link #appendJavaScript}
     */
    public String getAppendJavaScript()
    {
        return this.appendJavaScript;
    }

    /**
     * This is the setter method for the instance variable {@link #appendJavaScript}.
     *
     * @param _appendJavaScript the appendJavaScript to set
     */
    public void setAppendJavaScript(final String _appendJavaScript)
    {
        this.appendJavaScript = _appendJavaScript;
    }

    /**
     * This is the getter method for the instance variable {@link #dndType}.
     *
     * @return value of instance variable {@link #dndType}
     */
    public CharSequence getDndType()
    {
        return this.dndType;
    }

    /**
     * This is the setter method for the instance variable {@link #dndType}.
     *
     * @param _dndType the dndType to set
     */
    public void setDndType(final CharSequence _dndType)
    {
        this.dndType = _dndType;
    }

    /**
     * Static Method to get DnDBehavior with Source behavior.
     *
     * @return DnDBehavior with Source behavior.
     */
    public static DnDBehavior getSourceBehavior()
    {
        return new DnDBehavior(DnDBehavior.BehaviorType.SOURCE);
    }

    /**
     * Static Method to get DnDBehavior with Source behavior.
     *
     * @param _dndType dndtype to set
     * @return DnDBehavior with Source behavior.
     */
    public static DnDBehavior getSourceBehavior(final String _dndType)
    {
        return new DnDBehavior(DnDBehavior.BehaviorType.SOURCE, _dndType);
    }

    /**
     * Static Method to get DnDBehavior with item behavior.
     *
     * @param _dndType dndtype to set
     * @return DnDBehavior with item behavior.
     */
    public static DnDBehavior getItemBehavior(final String _dndType)
    {
        return new DnDBehavior(DnDBehavior.BehaviorType.ITEM, _dndType);
    }

    /**
     * Static Method to get DnDBehavior with item behavior.
     *
     * @return DnDBehavior with item behavior.
     */
    public static DnDBehavior getItemBehavior()
    {
        return new DnDBehavior(DnDBehavior.BehaviorType.ITEM);
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.components.menutree;

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

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.IRequestListener;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree;
import org.apache.wicket.extensions.markup.html.repeater.tree.Node;
import org.apache.wicket.extensions.markup.html.repeater.tree.theme.HumanTheme;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.efaps.ui.wicket.behaviors.update.IRemoteUpdateListener;
import org.efaps.ui.wicket.behaviors.update.IRemoteUpdateable;
import org.efaps.ui.wicket.models.objects.PagePosition;
import org.efaps.ui.wicket.models.objects.UIForm;
import org.efaps.ui.wicket.models.objects.UIMenuItem;
import org.efaps.ui.wicket.models.objects.UIStructurBrowser;
import org.efaps.ui.wicket.models.objects.UITable;
import org.efaps.ui.wicket.models.objects.grid.UIGrid;
import org.efaps.ui.wicket.pages.content.form.FormPage;
import org.efaps.ui.wicket.pages.content.grid.GridPage;
import org.efaps.ui.wicket.pages.content.structurbrowser.StructurBrowserPage;
import org.efaps.ui.wicket.pages.content.table.TablePage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.ui.wicket.resources.AbstractEFapsHeaderItem;
import org.efaps.ui.wicket.resources.EFapsContentReference;
import org.efaps.ui.wicket.util.Configuration;
import org.efaps.ui.wicket.util.Configuration.ConfigAttribute;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;

/**
 * @author The eFaps Team
 */
public class MenuTree
    extends NestedTree<UIMenuItem>
    implements IRemoteUpdateable, IRequestListener
{

    /**
     * Reference to icon for go into button.
     */
    public static final EFapsContentReference ICON_GOINTO = new EFapsContentReference(MenuTree.class, "GoInto.gif");

    /**
     * Reference to icon for go up button.
     */
    public static final EFapsContentReference ICON_GOUP = new EFapsContentReference(MenuTree.class, "GoUp.gif");

    /**
     * Reference to icon for closed child button.
     */
    public static final EFapsContentReference ICON_CHILDCLOSED = new EFapsContentReference(MenuTree.class,
                    "ChildClosed.gif");

    /**
     * Reference to icon for open child button.
     */
    public static final EFapsContentReference ICON_CHILDOPENED = new EFapsContentReference(MenuTree.class,
                    "ChildOpened.gif");

    /**
     * Reference to style sheet for the menutree.
     */
    public static final EFapsContentReference CSS = new EFapsContentReference(MenuTree.class, "MenuTree.css");

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Selected Component.
     */
    private Component selected = null;

    /**
     * Mapping of a key to menuitem.
     */
    private final Map<String, UIMenuItem> key2uimenuItem = new HashMap<>();

    /**
     * Constructor used for a new MenuTree.
     *
     * @param _wicketId wicket id of the component
     * @param _commandUUID uuid of the command
     * @param _oid oid
     * @param _selectCmdUUID UUID of the selected Command
     * @throws CacheReloadException on error
     */
    public MenuTree(final String _wicketId,
                    final UUID _commandUUID,
                    final String _oid,
                    final UUID _selectCmdUUID)
        throws CacheReloadException
    {
        super(_wicketId, new TreeMenuModel(_commandUUID, _oid));

        add(new HumanTheme());
        add(AttributeModifier.append("class", "eFapsTreeMenu"));
        add(new MenuUpdateBehavior());

        setDefault(_selectCmdUUID);
    }

    /**
     * Render to the web response the eFapsContentReference.
     *
     * @param _response Response object
     */
    @Override
    public void renderHead(final IHeaderResponse _response)
    {
        super.renderHead(_response);
        _response.render(AbstractEFapsHeaderItem.forCss(MenuTree.CSS));
    }

    /**
     * Set the default selected item.
     *
     * @param _selectCmdUUID UUID of the selected Command
     */
    public void setDefault(final UUID _selectCmdUUID)
    {
        final UIMenuItem menuItem = getProvider().getRoots().next();
        menuItem.setHeader(true);
        boolean hasDefault = false;
        for (final UIMenuItem childItem : menuItem.getChildren()) {
            if (_selectCmdUUID == null && childItem.isDefaultSelected()
                            || _selectCmdUUID != null && _selectCmdUUID.equals(childItem.getCommandUUID())) {
                hasDefault = true;
                childItem.setSelected(true);
            }
        }
        if (!hasDefault) {
            menuItem.setSelected(true);
        }
        expand(menuItem);
        expandChildren(menuItem);
    }

    /**
     * @param _menuItem menuitem the children will be expanded for
     */
    protected void expandChildren(final UIMenuItem _menuItem)
    {
        for (final UIMenuItem childItem : _menuItem.getChildren()) {
            if (childItem.isExpanded()) {
                expand(childItem);
            }
            expandChildren(childItem);
        }
    }

    @Override
    protected Component newContentComponent(final String _id,
                                            final IModel<UIMenuItem> _model)
    {
        final MenuItem menuitem = new MenuItem(_id, this, _model);
        if (_model.getObject().isSelected()) {
            this.selected = menuitem;
        }
        return menuitem;
    }

    @Override
    public Component newNodeComponent(final String _wicketId,
                                      final IModel<UIMenuItem> _model)
    {
        return new AbstractMenuNode(_wicketId, this, _model)
        {

            private static final long serialVersionUID = 1L;

            @Override
            protected Component createContent(final String _id,
                                              final IModel<UIMenuItem> _model)
            {
                return newContentComponent(_id, _model);
            }
        };
    }

    /**
     * Getter method for the instance variable {@link #selected}.
     *
     * @return value of instance variable {@link #selected}
     */
    public Component getSelected()
    {
        return this.selected;
    }

    /**
     * Setter method for instance variable {@link #selected}.
     *
     * @param _selected value for instance variable {@link #selected}
     */

    public void setSelected(final Component _selected)
    {
        this.selected = _selected;
    }

    /**
     * @param _commandUUID UUID of the command
     * @param _instanceKey instance key
     * @param _target the ajax target to use
     * @throws CacheReloadException on error
     */
    public void addChildMenu(final UUID _commandUUID,
                             final String _instanceKey,
                             final AjaxRequestTarget _target)
        throws CacheReloadException
    {
        final UIMenuItem menuItem = (UIMenuItem) getSelected().getDefaultModelObject();
        boolean old = false;
        for (final UIMenuItem child : menuItem.getChildren()) {
            if (child.getInstanceKey().equals(_instanceKey)
                            && child.getCommandUUID().equals(_commandUUID)) {
                old = true;
                child.setSelected(true);
                menuItem.setSelected(false);
                visitChildren(MenuItem.class, (_comp,
                 _visit) -> {
                    final Object object = _comp.getDefaultModelObject();
                    if (object != null && object instanceof UIMenuItem) {
                        if (((UIMenuItem) object).isSelected()) {
                            _target.add(getSelected());
                            setSelected(_comp);
                            _target.add(getSelected());
                            _visit.stop();
                        }
                    }
                });
                break;
            }
        }

        if (!old) {
            final UIMenuItem newMenuItem = new UIMenuItem(_commandUUID, _instanceKey);
            newMenuItem.setSelected(true);
            newMenuItem.setAncestor(menuItem);
            menuItem.getChildren().add(newMenuItem);
            expand(menuItem);
            expand(newMenuItem);
            menuItem.setSelected(false);
            _target.add(getSelected());
        }
    }

    /**
     * @param _menuItem child to be removed
     * @param _target Ajaxtarget
     */
    public void removeChild(final UIMenuItem _menuItem,
                            final AjaxRequestTarget _target)
    {
        final UIMenuItem selectedItem = (UIMenuItem) getSelected().getDefaultModelObject();

        final UIMenuItem ancestor = _menuItem.getAncestor();
        boolean nested = false;
        if (selectedItem.isChild(_menuItem) || selectedItem.equals(_menuItem)) {
            nested = true;
        }
        ancestor.getChildren().remove(_menuItem);
        if (nested) {
            expand(ancestor);
            ancestor.setSelected(true);
            visitChildren(MenuItem.class, (_comp,
             _visit) -> {
                if (_comp.getDefaultModelObject().equals(ancestor)) {
                    setSelected(_comp);
                    _visit.stop();
                }
            });
        } else {
            expand(ancestor);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void registerListener(final IRemoteUpdateListener _listener)
    {
        final MenuUpdateBehavior behavior = getBehaviors(MenuUpdateBehavior.class).get(0);
        behavior.register(_listener);
    }

    @Override
    public void onRequest()
    {
        final String key = getRequest().getRequestParameters().getParameterValue("D").toString();
        final UIMenuItem currentItem = this.key2uimenuItem.get(key);

        UIMenuItem menuItem = (UIMenuItem) getSelected().getDefaultModelObject();

        if (menuItem.isChild(currentItem) || menuItem.equals(currentItem)) {
            menuItem =  currentItem.getAncestor();
        }

        Page page;
        try {
            if (menuItem.getCommand().getTargetTable() != null) {
                if (menuItem.getCommand().getTargetStructurBrowserField() != null) {
                    page = new StructurBrowserPage(Model.of(new UIStructurBrowser(menuItem.getCommandUUID(),
                                    menuItem.getInstanceKey()).setPagePosition(PagePosition.TREE)),
                                    getPage().getPageReference());
                } else {
                    if ("GridX".equals(Configuration.getAttribute(ConfigAttribute.TABLE_DEFAULTTYPETREE))) {
                        page = new GridPage(Model.of(UIGrid.get(menuItem.getCommandUUID(), PagePosition.TREE)
                                        .setCallInstance(menuItem.getInstance())));
                    } else {
                        page = new TablePage(Model.of(new UITable(menuItem.getCommandUUID(), menuItem.getInstanceKey())
                                        .setPagePosition(PagePosition.TREE)), getPage().getPageReference());
                    }
                }
            } else {
                final UIForm uiForm = new UIForm(menuItem.getCommandUUID(), menuItem.getInstanceKey())
                                .setPagePosition(PagePosition.TREE);
                page = new FormPage(Model.of(uiForm), getPage().getPageReference());
            }
        } catch (final EFapsException e) {
            page = new ErrorPage(e);
        }
        setResponsePage(page);
    }

    /**
     * @param _key          key
     * @param _menuItem     menuitem
     */
    public void add(final String _key,
                    final UIMenuItem _menuItem)
    {
        this.key2uimenuItem.put(_key, _menuItem);
    }

    @Override
    public void expand(final UIMenuItem _menuItem)
    {
        super.expand(_menuItem);
        _menuItem.setExpanded(true);
    }

    @Override
    public void collapse(final UIMenuItem _menuItem)
    {
        super.collapse(_menuItem);
        _menuItem.setExpanded(false);
    }

    @Override
    public void updateNode(final UIMenuItem _menuItem,
                           final IPartialPageRequestHandler _target)
    {
        if (_target != null) {
            final IModel<UIMenuItem> model = getProvider().model(_menuItem);
            visitChildren(Node.class, (_node,
                            _visit) -> {
                if (model.equals(((Node<?>) _node).getModel())) {
                    _target.add(_node);
                    ((MarkupContainer) _node).visitChildren(Label.class, (_label,
                                    _visit1) -> _label.setDefaultModelObject(
                                                    ((UIMenuItem) _node.getDefaultModelObject()).getLabel()));
                    _visit.stop();
                }
                _visit.dontGoDeeper();
            });
            model.detach();
        }
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.pages.dialog;

import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.PageReference;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.event.EventType;
import org.efaps.admin.event.Parameter.ParameterValues;
import org.efaps.admin.event.Return;
import org.efaps.admin.event.Return.ReturnValues;
import org.efaps.ui.wicket.behaviors.dojo.RequireBehavior;
import org.efaps.ui.wicket.components.LabelComponent;
import org.efaps.ui.wicket.components.button.AjaxButton;
import org.efaps.ui.wicket.components.footer.AjaxSubmitCloseButton;
import org.efaps.ui.wicket.components.modalwindow.ModalWindowContainer;
import org.efaps.ui.wicket.components.modalwindow.UpdateParentCallback;
import org.efaps.ui.wicket.models.objects.ICmdUIObject;
import org.efaps.ui.wicket.pages.AbstractMergePage;
import org.efaps.ui.wicket.pages.content.AbstractContentPage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.ui.wicket.resources.AbstractEFapsHeaderItem;
import org.efaps.ui.wicket.resources.EFapsContentReference;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This Page renders a Dialog for Userinterference.<br>
 * e.g. "Do you really want to...?"
 *
 * @author The eFaps Team
 */
public class DialogPage
    extends AbstractMergePage
{
    /**
     * Reference to the StyleSheet of this Page stored in the eFaps-DataBase.
     */
    public static final EFapsContentReference CSS = new EFapsContentReference(DialogPage.class, "DialogPage.css");

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(DialogPage.class);

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 1L;

    /**
     * Reference to the page that opened this dialog.
     */
    private final PageReference pageReference;

    /**
     * Constructor used for a DialogPage that renders a Question like: "Are you
     * sure that??" with a Cancel and a SubmitButton.
     *
     * @param _pageReference Reference to the page that opened this dialog
     * @param _model the MenuItem that called this DialogPage
     * @param _oids oids which must be past on, in case of submit
     * @throws CacheReloadException the cache reload exception
     */
    public DialogPage(final PageReference _pageReference,
                      final IModel<ICmdUIObject> _model,
                      final String[] _oids)
        throws CacheReloadException
    {
        super(_model);
        this.pageReference = _pageReference;
        try {
            final ICmdUIObject menuItem = _model.getObject();

            final String cmdName = menuItem.getCommand().getName();

            add(new Label("textLabel", DBProperties.getProperty(cmdName + ".Question")).setOutputMarkupId(true));

            add(new AjaxSubmitBtn("submitButton",  _model, _oids, DialogPage.getLabel(cmdName, "Submit")));

            add(new AjaxCloseBtn("closeButton", DialogPage.getLabel(cmdName, "Cancel")));

            add(new RequireBehavior("dojo/query", "dojo/NodeList-dom"));
        } catch (final EFapsException e) {
            DialogPage.LOG.error("Catched", e);
        }
    }

    /**
     * Constructor setting the ModalWindow.
     *
     * @param _pageReference Reference to the page that opened this dialog
     * @param _value value is depending on parameter "_isSniplett" the key to a
     *            DBProperty or a snipplet
     * @param _isSniplett is it a snipplet or not
     * @param _goOn go on?
     */
    public DialogPage(final PageReference _pageReference,
                      final String _value,
                      final boolean _isSniplett,
                      final boolean _goOn)
    {
        this.pageReference = _pageReference;

        if (_isSniplett) {
            this.add(new LabelComponent("textLabel", _value));
        } else {
            this.add(new Label("textLabel", DBProperties.getProperty(_value + ".Message")));
        }
        if (_goOn) {
            final AjaxGoOnBtn ajaxGoOnLink = new AjaxGoOnBtn("submitButton", DialogPage.getLabel(_value, "Create"));
            add(ajaxGoOnLink);
        } else {
            this.add(new WebMarkupContainer("submitButton").setVisible(false));
        }
        final AjaxCloseBtn btn = new AjaxCloseBtn("closeButton", DialogPage.getLabel(_value, "Close"));
        btn.add(new KeyListenerBehavior());
        add(btn);
    }

    @Override
    public void renderHead(final IHeaderResponse _response)
    {
        super.renderHead(_response);
        _response.render(AbstractEFapsHeaderItem.forCss(DialogPage.CSS));
    }

    /**
     * Method that gets the Value for the Buttons from the DBProperties.
     *
     * @param _cmdName Name of the Command, that Label for the Button should be
     *            retrieved
     * @param _keytype type of the key e.g. "Cancel", "Submit", "Close"
     * @return Label
     */
    public static String getLabel(final String _cmdName,
                                   final String _keytype)
    {
        final String ret;
        if (DBProperties.hasProperty(_cmdName + ".Button." + _keytype)) {
            ret = DBProperties.getProperty(_cmdName + ".Button." + _keytype);
        } else {
            ret = DBProperties.getProperty("default.Button." + _keytype);
        }
        return ret;
    }

    /**
     * AjaxLink that closes the ModalWindow this Page was opened in.
     */
    public class AjaxGoOnBtn
        extends AjaxButton<Void>
    {

        /** Needed for serialization. */
        private static final long serialVersionUID = 1L;

        /**
         * Instantiates a new ajax go on btn.
         *
         * @param _wicketId wicket id of this component
         * @param _label the label
         */
        public AjaxGoOnBtn(final String _wicketId,
                           final String _label)
        {
            super(_wicketId, AjaxButton.ICON.ACCEPT.getReference(), _label);
            setSubmit(false);
        }

        @Override
        public void onRequest(final AjaxRequestTarget _target)
        {
            final AbstractContentPage page = (AbstractContentPage) DialogPage.this.pageReference.getPage();

            final AjaxSubmitCloseButton beh = page.visitChildren(AjaxSubmitCloseButton.class,
                            new IVisitor<Component, AjaxSubmitCloseButton>()
                {
                    @Override
                    public void component(final Component _component,
                                          final IVisit<AjaxSubmitCloseButton> _visit)
                    {
                        _visit.stop((AjaxSubmitCloseButton) _component);
                    }
                });
            beh.setValidated(true);
            final ModalWindowContainer modal = page.getModal();
            modal.close(_target);
        }
    }

    /**
     * AjaxLink that closes the ModalWindow this Page was opened in.
     */
    public class AjaxCloseBtn
        extends AjaxButton<Void>
    {

        /** Needed for serialization. */
        private static final long serialVersionUID = 1L;

        /**
         * Instantiates a new ajax close btn.
         *
         * @param _wicketId wicket id of this component
         * @param _label the label
         */
        public AjaxCloseBtn(final String _wicketId,
                            final String _label)
        {
            super(_wicketId, AjaxButton.ICON.CANCEL.getReference(), _label);
            setSubmit(false);
        }

        /**
         * @see org.apache.wicket.ajax.markup.html.AjaxLink#onClick(org.apache.wicket.ajax.AjaxRequestTarget)
         * @param _target request target
         */
        @Override
        public void onRequest(final AjaxRequestTarget _target)
        {
            DialogPage.this.pageReference.getPage().visitChildren(ModalWindowContainer.class,
                            new IVisitor<ModalWindowContainer, Void>()
                {
                    @Override
                    public void component(final ModalWindowContainer _modal,
                                          final IVisit<Void> _visit)
                    {
                        _modal.close(_target);
                    }
                });

            final StringBuilder bldr = new StringBuilder();
            bldr.append("var cD = top.frames[0].document").append(".getElementById('eFapsContentDiv');")
                .append("if(cD!=null){")
                    .append("cD.getElementsByTagName('input');")
                    .append("if(inp!=null){")
                        .append("  inp[0].focus();")
                    .append("}")
                .append("}");
            _target.appendJavaScript(bldr.toString());
        }
    }

    /**
     * AjaxLink that submits the Parameters and closes the ModalWindow.
     */
    public class AjaxSubmitBtn
        extends AjaxButton<ICmdUIObject>
    {

        /** Needed for serialization. */
        private static final long serialVersionUID = 1L;

        /**
         * the Oids that will be submitted.
         */
        private final String[] oids;

        /**
         * Form was validated.
         */
        private boolean validated = false;

        /**
         * Instantiates a new ajax submit btn.
         *
         * @param _wicketId wicket id of this component
         * @param _model model for this component
         * @param _oids oids
         * @param _label the label
         */
        public AjaxSubmitBtn(final String _wicketId,
                             final IModel<ICmdUIObject> _model,
                             final String[] _oids,
                             final String _label)
        {
            super(_wicketId, _model, AjaxButton.ICON.ACCEPT.getReference(), _label);
            this.oids = _oids;
            setSubmit(false);
        }

        /**
         * @see org.apache.wicket.ajax.markup.html.AjaxLink#onClick(org.apache.wicket.ajax.AjaxRequestTarget)
         * @param _target request target
         */
        @Override
        public void onRequest(final AjaxRequestTarget _target)
        {
            final ICmdUIObject model = getModelObject();
            try {
                if (isValidated() || validate(_target)) {
                    model.executeEvents(EventType.UI_COMMAND_EXECUTE, ParameterValues.OTHERS, this.oids);

                    DialogPage.this.pageReference.getPage().visitChildren(ModalWindowContainer.class,
                                    new IVisitor<ModalWindowContainer, Void>()
                        {

                            @Override
                            public void component(final ModalWindowContainer _modal,
                                                  final IVisit<Void> _visit)
                            {
                                _modal.setWindowClosedCallback(new UpdateParentCallback(
                                                DialogPage.this.pageReference, _modal));
                                _modal.setUpdateParent(true);
                                _modal.close(_target);
                            }
                        });
                }
            } catch (final EFapsException e) {
                throw new RestartResponseException(new ErrorPage(e));
            }
        }

        /**
         * Executes the Validation-Events related to the CommandAbstract which
         * called this Form.
         *
         * @param _target AjaxRequestTarget to be used in the case a ModalPage
         *            should be called
         * @return true if the Validation was valid, otherwise false
         * @throws EFapsException on error
         */
        private boolean validate(final AjaxRequestTarget _target)
            throws EFapsException
        {
            setValidated(true);
            boolean ret = true;
            boolean goOn = true;
            final ICmdUIObject cmdObject = (ICmdUIObject) getDefaultModelObject();
            final List<Return> returns = cmdObject.executeEvents(EventType.UI_VALIDATE,
                            ParameterValues.OTHERS, this.oids);
            final StringBuilder bldr = new StringBuilder();
            for (final Return oneReturn : returns) {
                if (oneReturn.get(ReturnValues.VALUES) != null || oneReturn.get(ReturnValues.SNIPLETT) != null) {
                    if (oneReturn.get(ReturnValues.VALUES) != null) {
                        bldr.append(oneReturn.get(ReturnValues.VALUES));
                    } else {
                        bldr.append(oneReturn.get(ReturnValues.SNIPLETT));
                    }
                    ret = false;
                    if (oneReturn.get(ReturnValues.TRUE) == null) {
                        goOn = false;
                    }
                } else {
                    if (oneReturn.get(ReturnValues.TRUE) == null) {
                        ret = false;
                        // that is the case if it is wrong configured!
                    }
                }
            }
            if (!ret) {
                getPage().visitChildren(Label.class, new IVisitor<Label, Void>()
                {
                    @Override
                    public void component(final Label _label,
                                          final IVisit<Void> _visit)
                    {
                        final Component label = new Label("textLabel", bldr.toString()).setOutputMarkupId(true)
                                        .setEscapeModelStrings(false);
                        _label.replaceWith(label);
                        _target.add(label);
                        _visit.stop();
                    }
                });
                if (!goOn) {
                    final StringBuilder js = new StringBuilder()
                        .append(" query(\".eFapsWarnDialogButton1\").style(\"display\", \"none\");");
                    _target.appendJavaScript(DojoWrapper.require(js, DojoClasses.query, DojoClasses.NodeListDom));
                }
            }
            return ret;
        }

        /**
         * Getter method for the instance variable {@link #validated}.
         *
         * @return value of instance variable {@link #validated}
         */
        public boolean isValidated()
        {
            return this.validated;
        }

        /**
         * Setter method for instance variable {@link #validated}.
         *
         * @param _validated value for instance variable {@link #validated}
         */
        public void setValidated(final boolean _validated)
        {
            this.validated = _validated;
        }
    }

    /**
     * CLass is used to listen to keyboard entries.
     */
    private static final class KeyListenerBehavior
        extends Behavior
    {

        /** Needed for serialization. */
        private static final long serialVersionUID = 1L;

        @Override
        public void renderHead(final Component _component,
                               final IHeaderResponse _response)
        {
            super.renderHead(_component, _response);
            final StringBuilder js = new StringBuilder();
            js.append("function pressed (_event) {")
                            .append("var b=Wicket.$('").append(_component.getMarkupId())
                            .append("'); if (typeof(b.onclick) != 'undefined') { b.onclick();  }")
                            .append("}").append("window.onkeydown = pressed;");
            _response.render(JavaScriptHeaderItem.forScript(js, DialogPage.class.getName()));
        }
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed 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.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.components.picker;

import java.util.Map;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.efaps.ui.wicket.models.field.UIPicker;
import org.efaps.ui.wicket.models.objects.AbstractUIPageObject;
import org.efaps.ui.wicket.util.EFapsKey;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class PickerCallBack
    implements ModalWindow.WindowClosedCallback
{
    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * MarkupId of the Target Component.
     */
    private final String targetMarkupId;

    /**
     * Refernce to the page.
     */
    private final PageReference pageReference;

    /**
     * @param _targetMarkupId   MarkupId of the target
     * @param _pageReference    refernce to the page te call back must be executed in
     *
     */
    public PickerCallBack(final String _targetMarkupId,
                          final PageReference _pageReference)
    {
        this.targetMarkupId = _targetMarkupId;
        this.pageReference = _pageReference;
    }

    /**
     * The actual Javascript that will be executed on close of the modal window.
     * @param _target Target
     */
    @Override
    public void onClose(final AjaxRequestTarget _target)
    {
        final AbstractUIPageObject pageObject = (AbstractUIPageObject) this.pageReference.getPage()
                        .getDefaultModelObject();
        if (pageObject.isOpenedByPicker()) {
            final UIPicker picker = pageObject.getPicker();
            pageObject.setPicker(null);
            if (picker.isExecuted()) {
                final Map<String, Object> map = picker.getReturnMap();
                final boolean escape = escape(map);
                final StringBuilder js = new StringBuilder();
                final String value = (String) map.get(EFapsKey.PICKER_VALUE.getKey());
                if (value != null) {
                    js.append("require(['dojo/dom'], function(dom){\n")
                        .append("dom.byId('").append(this.targetMarkupId).append("').value ='")
                        .append(escape ? StringEscapeUtils.escapeEcmaScript(StringEscapeUtils.escapeHtml4(value))
                                                    : value).append("';").append("});");
                }
                for (final String keyString : map.keySet()) {
                    // if the map contains a key that is not defined in this
                    // class it is assumed to be the name of a field
                    if (!(EFapsKey.PICKER_JAVASCRIPT.getKey().equals(keyString)
                                    || EFapsKey.PICKER_DEACTIVATEESCAPE.getKey().equals(keyString)
                                    || EFapsKey.PICKER_VALUE.getKey().equals(keyString))) {
                        final Object valueObj = map.get(keyString);
                        final String strValue;
                        final String strLabel;
                        if (valueObj instanceof String[] && ((String[]) valueObj).length == 2) {
                            strValue = escape && !((String[]) valueObj)[0].contains("Array(")
                                            ? StringEscapeUtils.escapeEcmaScript(((String[]) valueObj)[0])
                                            : ((String[]) valueObj)[0];
                            strLabel = escape && !((String[]) valueObj)[0].contains("Array(")
                                            ? StringEscapeUtils.escapeEcmaScript(((String[]) valueObj)[1])
                                            : ((String[]) valueObj)[1];
                        } else {
                            strValue = escape && !String.valueOf(valueObj).contains("Array(")
                                            ? StringEscapeUtils.escapeEcmaScript(String.valueOf(valueObj))
                                            : String.valueOf(valueObj);
                            strLabel = null;
                        }

                        js.append("eFapsSetFieldValue(")
                            .append(this.targetMarkupId == null ? 0 : "'" + this.targetMarkupId + "'").append(",'")
                            .append(keyString).append("',")
                            .append(strValue.contains("Array(") ? "" : "'")
                                        .append(strValue)
                                        .append(strValue.contains("Array(") ? "" : "'");
                        if (strLabel != null) {
                            js.append(",'").append(strLabel).append("'");
                        }
                        js.append(");");
                    }
                }
                if (map.containsKey(EFapsKey.PICKER_JAVASCRIPT.getKey())) {
                    js.append(map.get(EFapsKey.PICKER_JAVASCRIPT.getKey()));
                }
                _target.prependJavaScript(js.toString());
                picker.setExecuted(false);
            }
        }
    }

    /**
     * Check if for the current values the escape is activated.

     * Default: true,

     * key exits: null = false else evaluation of given String
     * @param _map map to be checked
     * @return boolean
     */
    private boolean escape(final Map<String, Object> _map)
    {
        boolean ret = true;
        if (_map.containsKey(EFapsKey.PICKER_DEACTIVATEESCAPE.getKey())) {
            final Object value = _map.get(EFapsKey.PICKER_DEACTIVATEESCAPE.getKey());
            if (value == null) {
                ret = false;
            } else {
                ret = BooleanUtils.toBoolean(EFapsKey.PICKER_DEACTIVATEESCAPE.getKey());
            }
        }
        return ret;
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.models.field.factories;

import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.api.ui.UIType;
import org.efaps.ui.wicket.components.picker.AjaxPickerButton;
import org.efaps.ui.wicket.components.values.CheckBoxField;
import org.efaps.ui.wicket.components.values.DropDownField;
import org.efaps.ui.wicket.components.values.NumberField;
import org.efaps.ui.wicket.components.values.RadioField;
import org.efaps.ui.wicket.components.values.SnippletField;
import org.efaps.ui.wicket.components.values.UploadField;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.IPickable;
import org.efaps.ui.wicket.models.objects.CheckBoxOption;
import org.efaps.ui.wicket.models.objects.DropDownOption;
import org.efaps.ui.wicket.models.objects.RadioOption;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
@SuppressWarnings("checkstyle:abstractclassname")
public final class UITypeFactory
    implements IComponentFactory
{

    /**
     * Factory Instance.
     */
    private static UITypeFactory FACTORY;

    @Override
    public Component getEditable(final String _wicketId,
                                 final AbstractUIField _uiField)
        throws EFapsException
    {
        return applies(_uiField) ? getEditableComp(_wicketId, _uiField) : null;
    }

    /**
     * Gets the editable comp.
     *
     * @param _wicketId the wicket id
     * @param _uiField the ui field
     * @return the editable comp
     * @throws EFapsException on error
     */
    protected Component getEditableComp(final String _wicketId,
                                        final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        switch (_uiField.getFieldConfiguration().getUIType()) {
            case SNIPPLET:
                if (!_uiField.getFieldConfiguration().isHideLabel()) {
                    _uiField.getFieldConfiguration().evalLabel(_uiField.getValue(), _uiField.getInstance());
                }
                final String html = String.valueOf(_uiField.getValue().getEditValue(
                                _uiField.getParent().getMode()));
                ret = new SnippletField(_wicketId, Model.of(html),  _uiField);
                break;
            case DROPDOWN:
                final List<DropDownOption> choices = DropDownOption.getChoices(_uiField.getValue()
                                .getEditValue(_uiField.getParent().getMode()));
                ret = new DropDownField(_wicketId, Model.of(_uiField), choices);
                break;
            case RADIO:
                final List<RadioOption> radios = RadioOption.getChoices(_uiField.getValue()
                                .getEditValue(_uiField.getParent().getMode()));
                ret = new RadioField(_wicketId, Model.of(_uiField), radios);
                break;
            case CHECKBOX:
                final List<CheckBoxOption> checkBoxes = CheckBoxOption.getChoices(_uiField,
                                _uiField.getValue().getEditValue(_uiField.getParent().getMode()));
                ret = new CheckBoxField(_wicketId, Model.of(_uiField), checkBoxes);
                break;
            case BUTTON:
                ret = new AjaxPickerButton(_wicketId, Model.<IPickable>of(_uiField));
                break;
            case NUMBER:
                ret = new NumberField(_wicketId, Model.of(_uiField), _uiField.getFieldConfiguration());
                break;
            case UPLOAD:
                ret = new UploadField(_wicketId, Model.of(_uiField), false);
                break;
            case UPLOADMULTIPLE:
                ret = new UploadField(_wicketId, Model.of(_uiField), true);
                break;
            default:
                break;
        }
        return ret;
    }

    @Override
    public Component getReadOnly(final String _wicketId,
                                 final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {

            switch (_uiField.getFieldConfiguration().getUIType()) {
                case SNIPPLET:
                    if (!_uiField.getFieldConfiguration().isHideLabel()) {
                        _uiField.getFieldConfiguration().evalLabel(_uiField.getValue(), _uiField.getInstance());
                    }
                    final Object value = _uiField.getValue().getReadOnlyValue(_uiField.getParent().getMode());
                    final String html = value == null ? null : String.valueOf(value);
                    ret = new SnippletField(_wicketId, Model.of(html), _uiField);
                    break;
                default:
                    break;
            }
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component getHidden(final String _wicketId,
                               final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {
            switch (_uiField.getFieldConfiguration().getUIType()) {
                case SNIPPLET:
                    final Object value = _uiField.getValue().getHiddenValue(_uiField.getParent().getMode());
                    final String html = value == null ? null : String.valueOf(value);
                    ret = new SnippletField(_wicketId, Model.of(html), _uiField);
                    break;
                default:
                    break;
            }
        }
        return ret;
    }

    @Override
    public boolean applies(final AbstractUIField _uiField)
        throws CacheReloadException
    {
        return !UIType.DEFAULT.equals(_uiField.getFieldConfiguration().getUIType());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getKey()
    {
        return UITypeFactory.class.getName();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getPickListValue(final AbstractUIField _uiField)
    {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<?> getCompareValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getStringValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return null;
    }

    /**
     * @return IComponentFactory instance
     */
    public static IComponentFactory get()
    {
        if (UITypeFactory.FACTORY == null) {
            UITypeFactory.FACTORY = new UITypeFactory();
        }
        return UITypeFactory.FACTORY;
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed 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.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.components.table.header;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.efaps.admin.ui.AbstractCommand.SortDirection;
import org.efaps.ui.wicket.models.objects.AbstractUIHeaderObject;
import org.efaps.ui.wicket.models.objects.UITableHeader;
import org.efaps.ui.wicket.resources.AbstractEFapsHeaderItem;
import org.efaps.ui.wicket.resources.EFapsContentReference;
import org.efaps.ui.wicket.util.EFapsKey;

/**
 * This class renders the Cells inside a Header, providing all necessary Links.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class HeaderCellPanel
    extends Panel
{
    /**
     * Reference to an icon from the eFaps DataBase.
     */
    public static final EFapsContentReference ICON_FILTER = new EFapsContentReference(HeaderCellPanel.class,
                                                                                "Filter.gif");

    /**
     * Reference to an icon from the eFaps DataBase.
     */
    public static final EFapsContentReference ICON_FILTERACTIVE = new EFapsContentReference(HeaderCellPanel.class,
                                                                                "FilterActive.gif");

    /**
     * Reference to an icon from the eFaps DataBase.
     */
    public static final EFapsContentReference ICON_SORTDESC = new EFapsContentReference(HeaderCellPanel.class,
                                                                                "SortDescending.gif");

    /**
     * Reference to an icon from the eFaps DataBase.
     */
    public static final EFapsContentReference ICON_SORTASC = new EFapsContentReference(HeaderCellPanel.class,
                                                                                "SortAscending.gif");

    /**
     * Reference to a stylesheet from the eFaps DataBase.
     */
    public static final EFapsContentReference CSS = new EFapsContentReference(HeaderCellPanel.class,
                                                                              "HeaderCellPanel.css");

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Constructor used to render only a CheckBoxCell or the placeholder in case of create.
     *
     * @param _wicketId wicket id for this component
     * @param _checkbox render a checkbox
     * @param _styleClass style class
     * @param _columnNumber number of the column
     */
    public HeaderCellPanel(final String _wicketId,
                           final boolean _checkbox,
                           final String _styleClass,
                           final int _columnNumber)
    {
        super(_wicketId);
        this.add(AttributeModifier.append("class", _styleClass
                        + (_columnNumber > 0 ? " eFapsCellFixedWidth" + _columnNumber : "")));
        if (_checkbox) {
            this.add(new Checkbox("checkBox"));
        } else {
            this.add(new WebMarkupContainer("checkBox").setVisible(false));
        }
        this.add(new WebMarkupContainer("sortlink").setVisible(false));
        this.add(new WebComponent("label").setVisible(false));
        this.add(new WebComponent("filterlink").setVisible(false));
    }

    /**
     * Constructor used to render a Cell for the Header with (depending on the model) SortLink, Filterlink etc.
     *
     * @param _wicketId wicket id for this component
     * @param _model model for this component
     * @param _uitable uitable this component sits in
     */
    public HeaderCellPanel(final String _wicketId,
                           final IModel<UITableHeader> _model,
                           final AbstractUIHeaderObject _uitable)
    {
        super(_wicketId, _model);

        final UITableHeader uiTableHeader = (UITableHeader) super.getDefaultModelObject();

        this.add(AttributeModifier.replace("title", uiTableHeader.getLabel()));

        this.add(new WebComponent("checkBox").setVisible(false));

        if (uiTableHeader.isSortable()) {
            final SortLink sortlink = new SortLink("sortlink", _model);

            if (uiTableHeader.getSortDirection() == SortDirection.NONE) {
                sortlink.add(AttributeModifier.append("class", "eFapsHeaderSort"));
            } else if (uiTableHeader.getSortDirection() == SortDirection.ASCENDING) {
                sortlink.add(AttributeModifier.append("class", "eFapsHeaderSortAscending"));
                sortlink.add(AttributeModifier.replace("style", " background-image: url("
                                + HeaderCellPanel.ICON_SORTASC.getImageUrl() + ");"));
            } else if (uiTableHeader.getSortDirection() == SortDirection.DESCENDING) {
                sortlink.add(AttributeModifier.append("class", "eFapsHeaderSortDescending"));
                sortlink.add(AttributeModifier.replace("style", " background-image: url("
                                + HeaderCellPanel.ICON_SORTDESC.getImageUrl() + ");"));
            }

            this.add(sortlink);
            final Label sortlabel = new Label("sortlabel", uiTableHeader.getLabel());
            sortlink.add(sortlabel);
            this.add(new WebComponent("label").setVisible(false));
        } else {
            this.add(new WebMarkupContainer("sortlink").setVisible(false));
            final Label label = new Label("label", uiTableHeader.getLabel());
            this.add(label);
        }

        if (uiTableHeader.isFilter()) {

            final AjaxFilterLink filterlink = new AjaxFilterLink("filterlink", _model);

            if (uiTableHeader.isFilterApplied() && _uitable.isFiltered()) {
                filterlink.add(AttributeModifier.append("class", "eFapsHeaderFilterActive"));
                filterlink.add(AttributeModifier.append("style", " background-image: url("
                                + HeaderCellPanel.ICON_FILTERACTIVE.getImageUrl() + ");"));
            } else {
                filterlink.add(AttributeModifier.append("class", "eFapsHeaderFilter"));
                filterlink.add(AttributeModifier.append("style", " background-image: url("
                                + HeaderCellPanel.ICON_FILTER.getImageUrl() + ");"));
            }
            this.add(filterlink);
        } else {
            this.add(new WebComponent("filterlink").setVisible(false));
        }
    }

    @Override
    public void renderHead(final IHeaderResponse _response)
    {
        super.renderHead(_response);
        _response.render(AbstractEFapsHeaderItem.forCss(HeaderCellPanel.CSS));
    }

    /**
     * Set the markupid into the model.
     *
     * @see org.apache.wicket.Component#onAfterRender()
     */
    @Override
    protected void onAfterRender()
    {
        super.onAfterRender();
        if (getDefaultModel() != null) {
            final UITableHeader headermodel = (UITableHeader) getDefaultModelObject();
            headermodel.setMarkupId(this.getMarkupId());
        }
    }

    /**
     * Class to render a checkbox that selects all checkboxes in this row.
     */
    public class Checkbox
        extends WebComponent
    {

        /**
         * Needed for serialization.
         */
        private static final long serialVersionUID = 1L;

        /**
         * @param _wicketId wicket id for this component
         */
        public Checkbox(final String _wicketId)
        {
            super(_wicketId);
        }

        /**
         * Make a checkbox.
         *
         * @see org.apache.wicket.Component#onComponentTag(org.apache.wicket.markup.ComponentTag)
         * @param _tag tag
         */
        @Override
        protected void onComponentTag(final ComponentTag _tag)
        {
            super.onComponentTag(_tag);
            _tag.put("type", "checkbox");
            _tag.put("onClick", getScript());
            _tag.put("name", EFapsKey.SELECTEALL_NAME.getKey());
        }

        /**
         * Get the script that will be added to the checkbox.
         *
         * @return String containing the script
         */
        private String getScript()
        {
            return new StringBuilder().append("var cb=document.getElementsByName('selectedRow');")
                            .append(" if(!isNaN(cb.length)) {")
                            .append(" for(var i=0;i<cb.length;i++){")
                            .append("   cb[i].checked=this.checked;}")
                            .append(" }else{")
                            .append(" cb.checked=this.checked;" + "}").toString();
        }
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.components.date;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.FormComponentPanel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.string.StringValue;
import org.efaps.admin.datamodel.ui.UIValue;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.event.EventDefinition;
import org.efaps.admin.event.EventType;
import org.efaps.api.ci.UIFormFieldProperty;
import org.efaps.db.Context;
import org.efaps.ui.wicket.behaviors.AjaxFieldUpdateBehavior;
import org.efaps.ui.wicket.components.values.IFieldConfig;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.FieldConfiguration;
import org.efaps.ui.wicket.models.field.set.UIFieldSet;
import org.efaps.ui.wicket.models.field.set.UIFieldSetValue;
import org.efaps.ui.wicket.models.objects.UITable;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.MutableDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wicketstuff.datetime.DateConverter;
import org.wicketstuff.datetime.StyleDateConverter;
import org.wicketstuff.datetime.markup.html.form.DateTextField;

/**
 * Class to render a datefield with picker and in case that a time is wanted
 * renders fields for hours and minute.
 *
 * @author The eFaps Team
 */
public class DateTimePanel
    extends FormComponentPanel<DateTime>
    implements IFieldConfig
{
    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(DateTimePanel.class);

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * DateConverter needed to enable date formating related to the locale.
     */
    private final DateConverter converter;

    /**
     * DateTime of this DateTimePanel.
     */
    private final DateTime datetime;

    /**
     * The datepicker for the panel.
     */
    private DatePickerBehavior datePicker;

    /**
     * Field underlying this Panel.
     */
    private AbstractUIField uiField;

    /**
     * Was the value already converted.
     */
    private boolean converted;

    /** The field config. */
    private FieldConfiguration fieldConfig;

    /**
     * Instantiates a new date time panel.
     *
     * @param _wicketId wicket id of this component
     * @param _model the model
     * @param _fieldConf the field conf
     * @param _dateObject object containing a DateTime, if null or not DateTime
     *                       a new DateTime will be instantiated
     * @param _time must the time be rendered also
     * @throws EFapsException on error
     */
    public DateTimePanel(final String _wicketId,
                         final Model<AbstractUIField> _model,
                         final FieldConfiguration _fieldConf,
                         final Object _dateObject,
                         final boolean _time)
        throws EFapsException
    {
        super(_wicketId, Model.<DateTime>of());
        this.uiField = _model.getObject();
        this.fieldConfig = _fieldConf;
        this.datetime = _dateObject == null || !(_dateObject instanceof DateTime)
                        ? new DateTime(Context.getThreadContext().getChronology())
                        : (DateTime) _dateObject;
        if (this.uiField != null) {
            setLabel(Model.of(getFieldConfig().evalLabel(this.uiField.getValue(), this.uiField.getInstance())));
        } else {
            setLabel(Model.of(getFieldConfig().getLabel()));
        }
        this.converter = new StyleDateConverter(false) {

            private static final long serialVersionUID = 1L;

            @Override
            protected DateTimeZone getTimeZone()
            {
                DateTimeZone ret = null;
                try {
                    ret = Context.getThreadContext().getTimezone();
                } catch (final EFapsException e) {
                    DateTimePanel.LOG.error("EFapsException", e);
                } finally {
                    if (ret == null) {
                        super.getTimeZone();
                    }
                }
                return ret;
            }
        };

        final DateTextField dateField = new DateTextField("date", new Model<>(this.datetime.toDate()),
                        this.converter)
        {

            private static final long serialVersionUID = 1L;

            @Override
            public String getInputName()
            {
                return DateTimePanel.this.getDateFieldName();
            }
        };
        this.add(dateField);

        if (getFieldConfig().hasProperty(UIFormFieldProperty.COLUMNS)) {
            add(new AttributeModifier("maxlength", getFieldConfig().getProperty(UIFormFieldProperty.COLUMNS)));
        }
        if (getFieldConfig().hasProperty(UIFormFieldProperty.WIDTH)
                        && this.uiField != null && !(this.uiField.getParent() instanceof UITable)) {
            add(new AttributeAppender("style", "width:" + getFieldConfig().getWidth(), ";"));
        }

        this.datePicker = new DatePickerBehavior();
        dateField.add(this.datePicker);

        final WebComponent hour = new WebComponent("hours")
        {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onComponentTag(final ComponentTag _tag)
            {
                super.onComponentTag(_tag);
                int hourTmp = DateTimePanel.this.datetime.getHourOfDay();
                if (use12HourFormat()) {
                    if (hourTmp == 0) {
                        hourTmp = 12;
                    }
                    if (hourTmp > 12) {
                        hourTmp = hourTmp - 12;
                    }
                }
                _tag.put("value", String.format("%02d", hourTmp));
                _tag.put("name", DateTimePanel.this.getHourFieldName());
                _tag.put("maxlength", 2);
            }

        };
        this.add(hour);
        hour.setVisible(_time);

        final WebComponent minutes = new WebComponent("minutes")
        {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onComponentTag(final ComponentTag _tag)
            {
                super.onComponentTag(_tag);
                _tag.put("value", String.format("%02d", DateTimePanel.this.datetime.getMinuteOfHour()));
                _tag.put("name", DateTimePanel.this.getMinuteFieldName());
                _tag.put("maxlength", 2);

            }
        };
        this.add(minutes);
        minutes.setVisible(_time);

        final WebComponent ampm = new WebComponent("ampm")
        {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onComponentTag(final ComponentTag _tag)
            {
                super.onComponentTag(_tag);
                _tag.put("name", DateTimePanel.this.getAmPmFieldName());
            }

            /**
             * set an am or pm option
             */
            @Override
            public void onComponentTagBody(final MarkupStream _markupStream,
                                              final ComponentTag _openTag)
            {
                super.onComponentTagBody(_markupStream, _openTag);
                final StringBuilder html = new StringBuilder();
                html.append("<option ");
                final int hourTmp = DateTimePanel.this.datetime.getHourOfDay();
                if (hourTmp < 12) {
                    html.append("selected=\"true\"");
                }
                html.append(">am</option>").append("<option ");
                if (hourTmp > 11) {
                    html.append("selected=\"true\"");
                }
                html.append(">pm</option>");
                replaceComponentTagBody(_markupStream, _openTag, html);
            }
        };
        this.add(ampm);
        ampm.setVisible(_time);

        if (!use12HourFormat()) {
            ampm.setVisible(false);
        }

        if (getFieldConfig() != null && getFieldConfig().getField().hasEvents(EventType.UI_FIELD_UPDATE)) {
            final List<EventDefinition> events = getFieldConfig().getField().getEvents(EventType.UI_FIELD_UPDATE);
            String eventName = "change";
            for (final EventDefinition event : events) {
                eventName = event.getProperty("Event") == null ? "change" : event.getProperty("Event");
            }
            dateField.add(new AjaxFieldUpdateBehavior(eventName, Model.of(this.uiField), false));
            if (_time) {
                hour.add(new AjaxFieldUpdateBehavior(eventName, Model.of(this.uiField), false));
                minutes.add(new AjaxFieldUpdateBehavior(eventName, Model.of(this.uiField), false));
                if (use12HourFormat()) {
                    ampm.add(new AjaxFieldUpdateBehavior(eventName, Model.of(this.uiField), false));
                }
            }
        }
        this.add(new WebMarkupContainer("seperator").setVisible(_time));
    }

    /**
     * Depending on the locale am/pm is used or not.
     *
     * @return true if 12 hour format else false
     */
    protected boolean use12HourFormat()
    {
        final String pattern = DateTimeFormat.patternForStyle("-S", getLocale());
        return pattern.indexOf('a') != -1 || pattern.indexOf('h') != -1 || pattern.indexOf('K') != -1;
    }

    /**
     * Getter method for the instance variable {@link #datePicker}.
     *
     * @return value of instance variable {@link #datePicker}
     */
    public DatePickerBehavior getDatePicker()
    {
        return this.datePicker;
    }

    /**
     * Getter method for instance variable {@link #fieldName}.
     *
     * @return value of instance variable {@link #fieldName}
     */
    public String getFieldName()
    {
        return getFieldConfig().getName();
    }

    /**
     * @return name for the field containing the date
     */
    public String getDateFieldName()
    {
        return getFieldName() + "_eFapsDate";
    }

    /**
     * @return name for the field containing the hours
     */
    public String getHourFieldName()
    {
        return getFieldName() + "_eFapsHour";
    }

    /**
     * @return name for the field containing the minutes
     */
    public String getMinuteFieldName()
    {
        return getFieldName() + "_eFapsMinute";
    }

    /**
     * @return name for the field containing am/pm
     */
    public String getAmPmFieldName()
    {
        return getFieldName() + "_eFapsAmPm";
    }

    /**
     * Method to get for the parameters returned from the form as a valid string. for a datetime
     *
     * @param _date date
     * @param _hour hour
     * @param _minute minutes
     * @param _ampm am/pm
     * @return valid string
     * @throws EFapsException on error
     */
    public List<StringValue> getDateAsString(final List<StringValue> _date,
                                             final List<StringValue> _hour,
                                             final List<StringValue> _minute,
                                             final List<StringValue> _ampm)
        throws EFapsException
    {
        final List<StringValue> ret = new ArrayList<>();
        final List<DateTime> dates = getDateList(_date, _hour, _minute, _ampm);
        for (final DateTime date : dates) {
            final DateTimeFormatter isofmt = ISODateTimeFormat.dateTime();
            ret.add(StringValue.valueOf(date.toString(isofmt)));
        }
        return ret;
    }

    /**
     * Method to get for the parameters returned from the form as a datetimes.
     *
     * @param _date date
     * @param _hour hour
     * @param _minute minutes
     * @param _ampm am/pm
     * @return valid string
     * @throws EFapsException on error
     */
    public List<DateTime> getDateList(final List<StringValue> _date,
                                      final List<StringValue> _hour,
                                      final List<StringValue> _minute,
                                      final List<StringValue> _ampm)
        throws EFapsException
    {
        final List<DateTime> ret = new ArrayList<>();
        if (_date != null) {
            Iterator<StringValue> hourIter = null;
            Iterator<StringValue> minuteIter = null;
            Iterator<StringValue> ampmIter = null;
            if (_hour != null) {
                hourIter = _hour.iterator();
            }
            if (_minute != null) {
                minuteIter = _minute.iterator();
            }
            if (_ampm != null) {
                ampmIter = _ampm.iterator();
            }

            for (final StringValue date : _date) {
                if (!date.isNull() && !date.isEmpty()) {
                    final DateTimeFormatter fmt = DateTimeFormat.forPattern(
                                    this.converter.getDatePattern(Context.getThreadContext().getLocale()))
                                    .withChronology(Context.getThreadContext().getChronology());
                    fmt.withLocale(getLocale());
                    final MutableDateTime mdt = fmt.parseMutableDateTime(date.toString());
                    if (hourIter != null) {
                        final StringValue hourStr = hourIter.next();
                        final int hour = Integer.parseInt(hourStr.toString("0"));
                        mdt.setHourOfDay(hour);
                        if (ampmIter != null) {
                            final StringValue ampmStr = ampmIter.next();
                            if ("am".equals(ampmStr.toString("am"))) {
                                if (hour == 12) {
                                    mdt.setHourOfDay(0);
                                }
                            } else {
                                if (hour != 12) {
                                    mdt.setHourOfDay(hour + 12);
                                }
                            }
                        }
                        if (minuteIter != null) {
                            final StringValue minuteStr = minuteIter.next();
                            final int minute = Integer.parseInt(minuteStr.toString("0"));
                            mdt.setMinuteOfHour(minute);
                        }
                    }
                    ret.add(mdt.toDateTime());
                }
            }
        }
        return ret;
    }

    /**
     * After rendering the datefields are added to the parent.
     */
    @Override
    protected void onAfterRender()
    {
        super.onAfterRender();
        final IDateListener container = this.findParent(IDateListener.class);
        if (container != null) {
            container.addDateComponent(this);
        }
    }

    @Override
    public void convertInput()
    {
        if (getUIField() != null) {
            try {
                this.converted = true;
                int i = 0;
                if (getUIField() instanceof UIFieldSetValue) {
                    final UIFieldSet cellset = ((UIFieldSetValue) getUIField()).getCellSet();
                    i = cellset.getIndex(getFieldName());
                }
                final List<StringValue> dates = getRequest().getRequestParameters().getParameterValues(
                                getDateFieldName());
                final List<StringValue> hours = getRequest().getRequestParameters().getParameterValues(
                                getHourFieldName());
                final List<StringValue> minutes = getRequest().getRequestParameters().getParameterValues(
                                getMinuteFieldName());
                final List<StringValue> ampms = getRequest().getRequestParameters().getParameterValues(
                                getAmPmFieldName());
                final List<DateTime> dateTimes = getDateList(dates, hours, minutes, ampms);
                if (!dateTimes.isEmpty()) {
                    setConvertedInput(dateTimes.get(i));
                }
            } catch (final EFapsException e) {
                DateTimePanel.LOG.error("Catched error on convert input", e);
            }
        }
    }

    /**
     * Getter method for the instance variable {@link #cellvalue}.
     *
     * @return value of instance variable {@link #cellvalue}
     */
    protected AbstractUIField getUIField()
    {
        return this.uiField;
    }

    @Override
    public void updateModel()
    {
        if (!this.converted) {
            convertInput();
        }
        setModelObject(getConvertedInput());
        try {
            if (getUIField() != null) {
                getUIField().setValue(UIValue.get(getUIField().getValue().getField(), getUIField().getValue()
                            .getAttribute(), getDefaultModelObject()));
            }
        } catch (final CacheReloadException e) {
            DateTimePanel.LOG.error("Catched error on updateModel", e);
        }
    }

    /**
     * @param _date date list
     * @param _hour hour list
     * @param _minute minute lits
     * @param _ampm ampm list
     * @param _htmlTable html; the error msg will be appended to
     * @return true if validated successfully, else false
     */
    public boolean validate(final List<StringValue> _date,
                            final List<StringValue> _hour,
                            final List<StringValue> _minute,
                            final List<StringValue> _ampm,
                            final StringBuilder _htmlTable)
    {
        boolean ret = true;
        Iterator<StringValue> hourIter = null;
        Iterator<StringValue> minuteIter = null;
        Iterator<StringValue> ampmIter = null;
        if (_hour != null) {
            hourIter = _hour.iterator();
        }
        if (_minute != null) {
            minuteIter = _minute.iterator();
        }
        if (_ampm != null) {
            ampmIter = _ampm.iterator();
        }
        final String fieldLabel = getLabel().getObject();
        if (hourIter != null) {
            int i = 1;
            while (hourIter.hasNext()) {
                final StringValue hourStr = hourIter.next();
                int hour = 1;
                try {
                    hour = Integer.parseInt(hourStr.toString("0"));
                } catch (final NumberFormatException e) {
                    _htmlTable.append("<tr><td>");
                    if (_hour.size() > 1) {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.hour.nonumber.line", new Object[] { fieldLabel, i}));
                    } else {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                    + ".validate.hour.nonumber", new Object[] { fieldLabel }));
                    }
                    _htmlTable.append("</td></tr>");
                    ret = false;
                    break;
                }
                // if am/pm the value must be 1 - 12 , else 0 - 24
                if (ampmIter == null && (hour < 0 || hour > 24)) {
                    _htmlTable.append("<tr><td>");
                    if (_hour.size() > 1) {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.hour.line", new Object[] { fieldLabel, i, 0, 24 }));
                    } else {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.hour", new Object[] { fieldLabel, 0, 24 }));
                    }
                    _htmlTable.append("</td></tr>");
                    ret = false;
                    break;
                } else if (ampmIter != null && (hour < 1 || hour > 12)) {
                    _htmlTable.append("<tr><td>");
                    if (_hour.size() > 1) {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.hour.line", new Object[] { fieldLabel, i, 1, 12 }));
                    } else {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.hour", new Object[] { fieldLabel, 1, 12 }));
                    }
                    _htmlTable.append("</td></tr>");
                    ret = false;
                    break;
                }
                i++;
            }
        }

        if (minuteIter != null) {
            int i = 1;
            while (minuteIter.hasNext()) {
                final StringValue minuteStr = minuteIter.next();
                int minute = 0;
                try {
                    minute = Integer.parseInt(minuteStr.toString("0"));
                } catch (final NumberFormatException e) {
                    _htmlTable.append("<tr><td>");
                    if (_hour.size() > 1) {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.minute.nonumber.line", new Object[] { fieldLabel, i}));
                    } else {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                    + ".validate.minute.nonumber", new Object[] { fieldLabel }));
                    }
                    _htmlTable.append("</td></tr>");
                    ret = false;
                    break;
                }
                if (minute < 0 || minute > 59) {
                    _htmlTable.append("<tr><td>");
                    if (_hour.size() > 1) {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.minute.line", new Object[] { fieldLabel, i, 0, 59 }));
                    } else {
                        _htmlTable.append(DBProperties.getFormatedDBProperty(DateTimePanel.class.getName()
                                        + ".validate.minute", new Object[] { fieldLabel, 0, 59 }));
                    }
                    _htmlTable.append("</td></tr>");
                    ret = false;
                    break;
                }
                i++;
            }
        }
        return ret;
    }

    @Override
    public FieldConfiguration getFieldConfig()
    {
        return this.fieldConfig;
    }
}


/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.job;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.Duration;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Abstract service containing code common to all job services
 */
@Slf4j
public abstract class AbstractPollingService {

    @Getter(AccessLevel.PROTECTED)
    private final ScheduledExecutorService executorService;

    @Getter(AccessLevel.PROTECTED)
    private final Duration timeout;

    /**
     * Constructs a new service with the default executor service
     */
    public AbstractPollingService(final Duration timeout) {
        this(Executors.newScheduledThreadPool(8), timeout);
    }

    /**
     * Constructs a new service with the given executor service
     */
    public AbstractPollingService(final ScheduledExecutorService executorService, final Duration timeout) {
        this.executorService = executorService;
        this.timeout = timeout;
    }

    /**
     * Shuts down the executor service. This method should be called when the job service is no longer needed, if the
     * default executor service was used
     */
    public void destroy() {
        log.debug("Shutting down executor service");

        executorService.shutdown();

        try {
            if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
                log.debug("Timed out waiting for executor service to die, calling shutdownNow");
                executorService.shutdownNow();
            }
        } catch (final InterruptedException e) {
            log.debug("Interrupted waiting for executor service to die, calling shutdownNow");
            executorService.shutdownNow();
        }
    }

}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.components.links;

import org.apache.wicket.PageReference;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.core.request.handler.PageProvider;
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.model.IModel;
import org.efaps.admin.ui.Menu;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.ui.wicket.components.RecentObjectLink;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.objects.UIMenuItem;
import org.efaps.ui.wicket.models.objects.UIStructurBrowser;
import org.efaps.ui.wicket.pages.content.AbstractContentPage;
import org.efaps.ui.wicket.pages.contentcontainer.ContentContainerPage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.ui.wicket.pages.main.MainPage;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class is used as link to load a page from an popup window inside the opener window.
 *
 * @author The eFaps Team
 */
public class LoadInTargetAjaxLink
    extends AjaxLink<AbstractUIField>
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(LoadInTargetAjaxLink.class);

    /**
     * target used for the script.
     */
    public enum ScriptTarget
    {
        /** top. */
        TOP("top"),
        /** opener. */
        OPENER("opener.top");

        /***/
        private String key;
        /**
         * @param _key key
         */
        ScriptTarget(final String _key)
        {
            this.key = _key;
        }
    }

    /**
     * target for this link.
     */
    private final ScriptTarget target;

    /** The content. */
    private final String content;

    /**
     * Constructor.
     *
     * @param _wicketId wicket id for this component
     * @param _model    model for this component
     * @param _content the content
     * @param _target   target for this link.
     */
    public LoadInTargetAjaxLink(final String _wicketId,
                                final IModel<AbstractUIField> _model,
                                final String _content,
                                final ScriptTarget _target)
    {
        super(_wicketId, _model);
        this.target = _target;
        this.content = _content;
    }

    /**
     * The tag must be overwritten.
     *
     * @param _tag tag to write.
     */
    @Override
    protected void onComponentTag(final ComponentTag _tag)
    {
        super.onComponentTag(_tag);
        _tag.setName("a");
        _tag.put("href", "#");
    }

    @Override
    public void onComponentTagBody(final MarkupStream _markupStream,
                                   final ComponentTag _openTag)
    {
        Object ret = null;
        try {
            if (this.content == null) {
                final AbstractUIField uiField = (AbstractUIField) getDefaultModelObject();
                ret = uiField.getValue().getReadOnlyValue(uiField.getParent().getMode());
            } else {
                ret = this.content;
            }
        } catch (final EFapsException e) {
            LOG.error("Catched error on setting tag body for: {}", this);
        }
        replaceComponentTagBody(_markupStream, _openTag, ret == null ? "" : String.valueOf(ret));
    }

    /**
     * Method to load something inside the opener window.
     *
     * @param _target AjaxRequestTarget
     */
    @Override
    @SuppressWarnings("checkstyle:illegalcatch")
    public void onClick(final AjaxRequestTarget _target)
    {
        Instance instance = null;
        try {
            if (this.target.equals(ScriptTarget.TOP)) {
                final PageReference reference = ((AbstractContentPage) getPage()).getCalledByPageReference();
                if (reference != null) {
                    final UIMenuItem menuItem = (UIMenuItem) ((ContentContainerPage) reference.getPage()).getMenuTree()
                                    .getSelected().getDefaultModelObject();
                    final RecentObjectLink link = new RecentObjectLink(menuItem);
                    if (link != null) {
                        ((EFapsSession) getSession()).addRecent(link);
                    }
                }
            }
            final AbstractUIField uiField = super.getModelObject();
            if (uiField.getInstanceKey() != null) {
                Menu menu = null;
                try {
                    instance = uiField.getInstance();
                    menu = Menu.getTypeTreeMenu(instance.getType());
                } catch (final Exception e) {
                    if (menu == null) {
                        throw new EFapsException(LoadInTargetAjaxLink.class, "NoTreeMenu", instance);
                    }
                }

                final ContentContainerPage page = new ContentContainerPage(menu.getUUID(), uiField.getInstanceKey(),
                                uiField.getParent() instanceof UIStructurBrowser);
                final CharSequence url = urlFor(new RenderPageRequestHandler(new PageProvider(page)));
                // touch the page to ensure that the pagemanager stores it to be accessible
                getSession().getPageManager().touchPage(page);
                final StringBuilder js = new StringBuilder()
                    .append(this.target.key).append(".dijit.registry.byId(\"").append("mainPanel")
                    .append("\").set(\"content\", dojo.create(\"iframe\",{")
                    .append("\"id\": \"").append(MainPage.IFRAME_ID)
                    .append("\",\"src\": \"./wicket/").append(url)
                    .append("\",\"style\": \"border: 0; width: 100%; height: 99%\"")
                    .append("}));");
                _target.appendJavaScript(js);
            }
        } catch (final EFapsException e) {
            throw new RestartResponseException(new ErrorPage(e));
        }
    }

    /**
     * Getter method for the instance variable {@link #content}.
     *
     * @return value of instance variable {@link #content}
     */
    protected String getContent()
    {
        return this.content;
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed 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.efaps.ui.wicket.models.field.factories;

import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.admin.datamodel.ui.PasswordUI;
import org.efaps.ui.wicket.components.values.PasswordField;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.util.EFapsException;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
@SuppressWarnings("checkstyle:abstractclassname")
public final class PasswordUIFactory
    extends AbstractUIFactory
{

    /**
     * Factory Instance.
     */
    private static PasswordUIFactory FACTORY;

    /**
     * Singelton.
     */
    protected PasswordUIFactory()
    {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component getEditable(final String _wicketId,
                                 final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {
            ret = new PasswordField(_wicketId, Model.of(_uiField), _uiField.getFieldConfiguration());
        }
        return ret;
    }

    @Override
    public Component getHidden(final String _wicketId,
                               final AbstractUIField _uiField)
        throws EFapsException
    {
        // does not have a hidden
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean applies(final AbstractUIField _uiField)
        throws EFapsException
    {
        return _uiField.getValue().getUIProvider() instanceof PasswordUI && _uiField.editable();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getReadOnlyValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        // does not have an readonly!
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getKey()
    {
        return PasswordUIFactory.class.getName();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getPickListValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<?> getCompareValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return null;
    }

    /**
     * @return IComponentFactory instance
     */
    public static IComponentFactory get()
    {
        if (PasswordUIFactory.FACTORY == null) {
            PasswordUIFactory.FACTORY = new PasswordUIFactory();
        }
        return PasswordUIFactory.FACTORY;
    }
}