/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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 com.queplix.core.client.controls.memo;

import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.jpavel.gwt.wysiwyg.client.EditorUtils;
import com.queplix.core.client.app.vo.uisettings.DialogUISettings;
import com.queplix.core.client.common.StringUtil;
import com.queplix.core.client.common.event.Event;
import com.queplix.core.client.common.event.EventListener;
import com.queplix.core.client.common.ui.resizable.Resizable;
import com.queplix.core.client.controls.QFormElementView;
import com.queplix.core.client.frames.htmledit.HtmlEditFrame;

/**
 * Memo contol inline view variant implementation.
 *
 * @author Sultan Tezadov
 * @since 22 Feb 2007
 */
public class QMemoViewImplInline extends QMemoViewImpl
        implements EventListener {
    private Widget activeControl;

    private int lastVisibleWidth;
    private int lastVisibleHeight;

    private static final String VIEW_DEFAULT_WIDTH = HtmlEditFrame.DEFAULT_WIDTH
            + "px";
    private static final String VIEW_DEFAULT_HEIGHT = HtmlEditFrame
            .DEFAULT_HEIGHT + "px";

    private static final String SEARCH_DEFAULT_WIDTH =
            (HtmlEditFrame.DEFAULT_WIDTH / 2) + "px";
    private static final String SEARCH_DEFAULT_HEIGHT = HtmlEditFrame
            .DEFAULT_HEIGHT + "px";

    private String clientWidth;
    
    private String textBackup;
    
    private boolean ignoreOnModelChanged;
    
    protected static class QueplixScrollPanel extends ScrollPanel
            implements Resizable {
        public void setOffsetHeight(int height) {
            super.setHeight(StringUtil.pixelToSize(height));
        }

        public void setOffsetWidth(int width) {
            super.setWidth(StringUtil.pixelToSize(width));
        }
    }

    private QueplixScrollPanel htmlViewPanel;

    private String originalText = "";
    private HorizontalPanel fieldPanel;

    public QMemoViewImplInline(QMemoModelImpl model, int layout) {
        super(model, layout);
    }

    protected DialogUISettings getUISettings() {
        return null;
    }

    public void showPopup() {
    }

    protected int getButtonWidth() {
        return 0;
    }

    protected void initGUI() {
        super.initGUI();
        initGUIVisible();
    }

    private void initGUIVisible() {
        fieldPanel = new HorizontalPanel();
        setTextAreaWidth();
        fieldPanel.add(textArea);
        fieldPanel.add(emptyButton);
        addToPanel(fieldPanel);
        activeControl = textArea;

        textArea.addFocusListener(new FocusListener() {
            public void onFocus(Widget sender) {
                getEventSource().fireEvent(
                        QFormElementView.Events.TEXTAREA_FOCUSED);
            }

            public void onLostFocus(Widget sender) {
                eventHandlers.handleEvent(saveEvent);
                getEventSource().fireEvent(
                        QFormElementView.Events.TEXTAREA_FOCUS_LOST);
            }
        });
        textArea.addKeyboardListener(new KeyboardListener() {
            public void onKeyDown(Widget sender, char keyCode, int modifiers) {
            }

            public void onKeyPress(Widget sender, char keyCode, int modifiers) {
            }

            public void onKeyUp(Widget sender, char keyCode, int modifiers) {
                eventHandlers.handleEvent(saveEvent);
            }
        });

        htmlEditorFrame.addEventListener(this);
        htmlViewPanel = new QueplixScrollPanel();
        setHtmlViewPanelWidth();
        htmlViewPanel.add(html);
        html.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
        htmlViewPanel.setStyleName("html_viewer");

        initPanel();
    }

    public void onEvent(Event event, Widget sender) {
        getEventSource().fireEvent(event);
    }

    protected void contentChanged() {
        if(getControlType() == QMemoView.MODE_EDIT
                || getControlType() == QMemoView.MODE_NEW) {
            textBackup = StringUtil.nullToEmpty(model.getData().getText());
            String additionalText = htmlEditorFrame.getText(null);
            String textForData = originalText;
            if(!additionalText.equals("")) {
                textForData = htmlEditorFrame.getText(originalText);
            }
            if(htmlEditorFrame.isShowFrame()) {
                textForData = StringUtil.nullToEmpty(textForData);
                if(!textForData.equals("") && !HtmlEditFrame.isHTML(
                        textForData)) {
                    textForData += HtmlEditFrame.HTML_INDICATOR;
                }
            } else {
                textForData = textForData.replaceAll(
                        HtmlEditFrame.HTML_INDICATOR, "");
            }
            textArea.setText(textForData);
            ignoreOnModelChanged = true;
            eventHandlers.handleEvent(saveEvent);
            ignoreOnModelChanged = false;
        }
    }
    
    public void applyModification() {
        if (getControlType() == QMemoView.MODE_EDIT || getControlType() == QMemoView.MODE_NEW) {
            htmlEditorFrame.setLockedText(originalText);
            htmlEditorFrame.setHasRecords(!StringUtil.isStringEmpty(originalText));
            onModelDataChanged();
        }
    }
    
    public void revertModification() {
        if (getControlType() == QMemoView.MODE_EDIT || getControlType() == QMemoView.MODE_NEW) {
            textArea.setText(textBackup);
            ignoreOnModelChanged = true;
            eventHandlers.handleEvent(saveEvent);
            ignoreOnModelChanged = false;
        }
    }

    public void onModelDataChanged() {
        if (ignoreOnModelChanged) {
            return;
        }
        super.onModelDataChanged();
        refreshGUI();
        htmlEditorFrame.resetEditor();
        originalText = StringUtil.nullToEmpty(model.getData().getText());
        htmlEditorFrame.setHasRecords(!StringUtil.isStringEmpty(originalText));
    }

    protected void replaceActiveControl(Widget activeControl,
                                        Widget newControl) {
        int width = activeControl.getOffsetWidth();
        int height = activeControl.getOffsetHeight();
        if(height > 0 && width > 0) {
            lastVisibleWidth = width;
            lastVisibleHeight = height;
        }
        fieldPanel.clear();
        fieldPanel.add(newControl);
        fieldPanel.add(emptyButton);
        if(getColSpan() > 1) {
            if(width == 0 && height == 0) {
                width = lastVisibleWidth;
                height = lastVisibleHeight;
            }
            ((Resizable) newControl).setOffsetWidth(width);
            ((Resizable) newControl).setOffsetHeight(height);
        } else if(clientWidth == null) {
            switch(getControlType()) {
                case CONTROL_TEXTAREA:
                    setTextAreaWidth();
                    break;
                case CONTROL_HTML_VIEWER:
                    setHtmlViewPanelWidth();
                    break;
            }
        } else {
            switch(getControlType()) {
                case CONTROL_TEXTAREA:
                    textArea.setWidth(clientWidth);
                    break;
                case CONTROL_HTML_VIEWER:
                    htmlViewPanel.setWidth(clientWidth);
                    break;
            }
        }
        this.activeControl = newControl;
    }

    private void setTextAreaWidth() {
        textArea.setWidth(SEARCH_DEFAULT_WIDTH);
    }

    private void setHtmlViewPanelWidth() {
        htmlViewPanel.setWidth(VIEW_DEFAULT_WIDTH);
    }

    public void setRowSpan(int rowSpan) {
        if(rowSpan == 0) {
            return;
        }
        super.setRowSpan(rowSpan);
        if(rowSpan > 10) {
            int height = (HtmlEditFrame.DEFAULT_HEIGHT / 10) * rowSpan;
            textArea.setOffsetHeight(height);
            htmlViewPanel.setOffsetHeight(height);
            htmlEditorFrame.setOffsetHeight(height);
        } else {
            textArea.setHeight(SEARCH_DEFAULT_HEIGHT);
            htmlViewPanel.setHeight(VIEW_DEFAULT_HEIGHT);
            htmlEditorFrame.setOffsetHeight(HtmlEditFrame.DEFAULT_HEIGHT);
        }
    }

    private void refreshGUI() {
        Widget control = textArea;
        switch(getControlType()) {
            case CONTROL_TEXTAREA:
                control = textArea;
                break;
            case CONTROL_HTML_EDITOR:
                if(EditorUtils.isGecko() && activeControl != htmlEditorFrame) {
                    htmlEditorFrame = new HtmlEditFrame(model);
                    htmlEditorFrame.setupLockedPanelVisibility();
                    htmlEditorFrame.addEventListener(this);
                }
                control = htmlEditorFrame;
                break;
            case CONTROL_HTML_VIEWER:
                control = htmlViewPanel;
                break;
        }
        if(activeControl != control) {
            replaceActiveControl(activeControl, control);
            //do not remove following code to the switch
            if(getControlType() == CONTROL_HTML_EDITOR) {
                htmlEditorFrame.setupEditor(originalText);
            }
        }
        refreshGUIData();
        //todo as per discussion with [AM] it is needed to fix form boundaries, but it doesn't work now, find
        //better decision without of mainframe realization dependency
//        getEventSource().fireEvent(MainFrameFA.Events.FORM_ACTIVATED);
    }

    protected void onModeChanged(int newMode) {
        refreshGUI();
    }

    protected void setEnabled(boolean isEnabled) {
    }

    public void setOffsetWidth(int width) {
        ((Resizable) activeControl).setOffsetWidth(width);
    }

    public void setOffsetHeight(int height) {
        ((Resizable) activeControl).setOffsetHeight(height);
    }

    public Widget getActiveControl() {
        return activeControl;
    }

    public int getCaptionOffsetWidth() {
        return captionLabel.getOffsetWidth();
    }

    public int getFilledWidth() {
        return super.getFilledWidth() + emptyButton.getOffsetWidth();
    }

    public int getClientWidth() {
        return activeControl.getOffsetWidth();
    }

    public void setClientWidth(String clientWidth) {
        this.clientWidth = clientWidth;
        activeControl.setWidth(clientWidth);
        int width = activeControl.getOffsetWidth();
        int height = activeControl.getOffsetHeight();
        if(height > 0 && width > 0) {
            lastVisibleWidth = width;
            lastVisibleHeight = height;
        }
    }

    public boolean alignableAsHorizontal() {
        return !isVerticalLayout();
    }

    public boolean canBeCoupled(int coupleType) {
        return false;
    }

}
