/*
 * Copyright 2006 Pavel Jbanov.
 *
 * 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 com.jpavel.gwt.wysiwyg.client;

import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.queplix.core.client.common.StringUtil;
import com.queplix.core.client.common.event.EventSource;
import com.queplix.core.client.controls.QFormElementView;

public class EditorWYSIWYG extends Composite implements FocusListener {
    
    private Editor editor;
    
    private VerticalPanel vp;
    private EditorIframe frame;
    private TextArea textArea;
    
    private boolean showFrame = true;
    
    private boolean isFrameFocused;
    
    public boolean isFrameFocused() {
        return isFrameFocused;
    }
    
    // -------------------- public events ------------------------
    private EventSource eventSource = new EventSource(this);
    
    public EventSource getEventSource() {
        return eventSource;
    }
    // ----------------- end of public events --------------------
    
    public EditorWYSIWYG(Editor _editor) {
        this.editor = _editor;
        
        vp = new VerticalPanel();
        vp.setWidth("100%");
        
        frame = new EditorIframe();
        frame.setWidth("100%");
        
        frame.addFocusListener(this);
        
        // this is done on purpose...
        if (EditorUtils.isGecko()) {
            frame.addMouseOverListener(new EditorMouseOverListener() {
                public void onMouseOver(Widget widget) {
                    enableDesignMode();
                    frame.removeMouseOverListener(this);
                }
            });
        }
        
        textArea = new TextArea();
        textArea.addStyleName("styled_input");
        textArea.setWidth("100%");
        textArea.addFocusListener(this);
        
        frame.setVisible(true);
        textArea.setVisible(false);
        
        vp.add(frame);
        vp.add(textArea);
        
        initWidget(vp);
    }
    
    //<body CONTENTEDITABLE=\"true\" onload=’document.designMode = \"On\";’
    public native void initFrame(Element oIframe)/*-{
            var oDoc = oIframe.contentWindow || oIframe.contentDocument;
            if (oDoc.document) {
                oDoc = oDoc.document;
            }
            oDoc.write("<html><body style='border:none; margin:0px; padding: 5px; font-family: Tahoma; font-size: 12px;'></body></html>");
            oDoc.close();
            oIframe.contentWindow.focus();
        }-*/;
    
    
    private boolean editModeOn = false;
    
    public void enableDesignMode() {
        if (!editModeOn) {
            _enableDesignMode(frame.getElement());
            editModeOn = true;
        }
    }
    
    private native void _enableDesignMode(Element oIframe)/*-{
            var oDoc = oIframe.contentWindow || oIframe.contentDocument;
            if (!oDoc) {
               $wnd.alert("bug _enableDesignMode");
            }
            if (oDoc.document) {
                oDoc = oDoc.document;
            }
            oDoc.designMode = 'On';
        }-*/;
    
    public void setHTML(String _html) {
        textArea.setText(_html);
        _setHTML(frame.getElement(), _html);
    }
    
    private native void _setHTML(Element oIframe, String _html)/*-{
            var oDoc = oIframe.contentWindow || oIframe.contentDocument;
                                                                
            if (!oDoc) {
               $wnd.alert("bug _setHTML");
            }
                                                                
            if (oDoc.document) {
                oDoc = oDoc.document;
            }
            oDoc.body.innerHTML = "";
            oDoc.write(_html);
            oDoc.close();
     }-*/;
    
    public String getHTML() {
        return showFrame ? _getHTML(frame.getElement()) : textArea.getText();
    }
    
    public native String _getHTML(Element oIframe)/*-{
            var oDoc = oIframe.contentWindow || oIframe.contentDocument;
            if (!oDoc) {
               $wnd.alert("bug _getHTML");
            }
                                                   
            if (oDoc.document) {
                oDoc = oDoc.document;
            }
            return oDoc.body.innerHTML;
        }-*/;
    
    
    public native void setCursorToTheEnd(Element oIframe)/*-{
        var oDoc = oIframe.contentWindow || oIframe.contentDocument;
        if (!oDoc) {
           $wnd.alert("bug setCursorToTheEnd");
        }
                                                           
        if (oDoc.document) {
            oDoc = oDoc.document;
        }

        var el = oDoc.body.innerHTML;
        var len = el.length;
        if (el.setSelectionRange) {
            el.setSelectionRange(len, len);
        } else if (el.createTextRange) {
            var range = el.createTextRange();
            range.collapse(true);
            range.moveEnd('character', len);
            range.moveStart('character', len);
            range.select();
        }
    }-*/;
    
    public void appendHTML(String html) {
        setHTML(getHTML() + html);
        EditorUtils.doFocus(frame.getElement());
        EditorUtils.oldDoFocus(frame.getElement());
        setCursorToTheEnd(frame.getElement());
    }

    public void setHeight(String height) {
        vp.setHeight(height);
        frame.setHeight(height);
        textArea.setHeight(height);
    }
    
    public void setWidth(String width) {
        vp.setWidth(width);
        frame.setWidth(width);
        textArea.setWidth(width);
    }
    
    public EditorIframe getFrame() {
        return frame;
    }
    
    public boolean isShowFrame() {
        return showFrame;
    }
    
    public void toggleView() {
        if (this.showFrame) {
            String text = StringUtil.htmlToText(getHTML());
            textArea.setText(text);
            
            textArea.setHeight("" + frame.getOffsetHeight() + "px");
            textArea.setWidth("" + frame.getOffsetWidth() + "px");
            
            frame.setVisible(false);
            textArea.setVisible(true);
            
            this.showFrame = false;
            
            editor.getEditorToolbar().switchToSmall();
        } else {
            String newHtml = StringUtil.textToHtml(textArea.getText());
            
            textArea.setVisible(false);
            frame.setVisible(true);
            
            setHTML(newHtml);
            
            this.showFrame = true;
            
            editor.getEditorToolbar().switchToFull();
        }
    }
    
    public void pasteHTML(String html) {
        if(!EditorUtils.isGecko()) {
            _pasteHTML(html, frame.getElement());
        } else {
            _pasteHTMLGeco(html, frame.getElement());
        }
    }
    
    private native void _pasteHTML(String html, Element oIframe) /*-{
        var oDoc = oIframe.contentWindow || oIframe.contentDocument;
        if (!oDoc) {
            $wnd.alert("bug _pasteHTML");
        }
        if (oDoc.document) {
            oDoc = oDoc.document;
        }
        var sel = oDoc.selection;
        if (sel != null) {
            var rng = sel.createRange();
            if (rng != null) {
                rng.pasteHTML(html);
            }
        }
    }-*/;
    
    private native void _pasteHTMLGeco(String html, Element oIframe) /*-{
        var oDoc = oIframe.contentWindow || oIframe.contentDocument;
        if (!oDoc) {
            $wnd.alert("bug _pasteHTML Geco");
        }
        if (oDoc.document) {
            oDoc = oDoc.document;
        }

        var sel = oDoc.selection.createRange(); //oDoc.selection;
        //var range = sel.getRangeAt(0);
        //range.pasteHTML(html);
        sel.pasteHTML(html);        
     }-*/;

    public void onFocus(Widget sender) {
        isFrameFocused = true;
        eventSource.fireEvent(QFormElementView.Events.TEXTAREA_FOCUSED);
    }

    public void _onLostFocus() {
        eventSource.fireEvent(QFormElementView.Events.TEXTAREA_FOCUS_LOST);
    }
    
    public void onLostFocus(Widget sender) {
        isFrameFocused = false;
        _onLostFocus();
    }
}
