/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.nbform;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import org.netbeans.core.spi.multiview.CloseOperationState;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.MultiViewElementCallback;
import org.netbeans.modules.form.FormDesigner;
import org.netbeans.modules.form.FormEditor;
import org.netbeans.modules.form.FormLoaderSettings;
import org.netbeans.modules.form.FormUtils;
import org.netbeans.modules.form.assistant.AssistantModel;
import org.netbeans.modules.form.assistant.AssistantView;
import org.openide.actions.FileSystemAction;
import org.openide.awt.StatusDisplayer;
import org.openide.awt.UndoRedo;
import org.openide.util.HelpCtx;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.actions.SystemAction;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.TopComponent;

@MultiViewElement.Registration(
    displayName="#CTL_DesignTabCaption",
    iconBase=FormEditorSupport.iconURL,
    persistenceType=TopComponent.PERSISTENCE_NEVER,
    preferredID=FormEditorSupport.MV_FORM_ID,
    mimeType="text/x-form",
    position=2000
)
public class FormDesignerTC extends TopComponent implements MultiViewElement {

    private FormEditorSupport formEditorSupport;
    private FormDesigner formDesigner;
    private PropertyChangeListener designerListener;

    private FormDesignerLookup lookup;

    private AssistantView assistantView;
    private PreferenceChangeListener settingsListener;

    private MultiViewElementCallback multiViewObserver;

    private PreLoadTask preLoadTask;

    private static String iconURL =
        "org/netbeans/modules/form/resources/formDesigner.gif"; // NOI18N

    public FormDesignerTC(Lookup lkp) {
        this(lkp.lookup(FormEditorSupport.class));
    }
    
    FormDesignerTC(FormEditorSupport formEditorSupport) {
        this.formEditorSupport = formEditorSupport;
        lookup = new FormDesignerLookup();
        createDesigner();
        associateLookup(lookup);
        setIcon(ImageUtilities.loadImage(iconURL));
        setLayout(new BorderLayout());
        setMinimumSize(new Dimension(10, 10));
    }

    private void createDesigner() {
        formDesigner = new FormDesigner(formEditorSupport.getFormEditor(true));
        if (designerListener == null) {
            designerListener = new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (FormDesigner.PROP_TOP_DESIGN_COMPONENT.equals(evt.getPropertyName())) {
                        formEditorSupport.updateMVTCDisplayName();
                    }
                }
            };
        }
        formDesigner.addPropertyChangeListener(designerListener);
        lookup.setLookupFromDesigner(formDesigner);
    }

    @Override
    protected String preferredID() {
        return formEditorSupport.getFormDataObject().getName();
    }

    // only MultiViewDescriptor is stored, not MultiViewElement
    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_NEVER;
    }

    @Override
    public HelpCtx getHelpCtx() {
        return new HelpCtx("gui.formeditor"); // NOI18N
    }

    @Override
    public void componentOpened() {
        super.componentOpened();
    }

    @Override
    public void componentClosed() {
        super.componentClosed();
        closeDesigner();
    }

    private FormEditorSupport closeDesigner() {
        if (formDesigner != null) {
            formDesigner.removePropertyChangeListener(designerListener);
            formDesigner.close();
        }
        removeAll();
        if (preLoadTask != null) { // designer closing before form loading started
            StatusDisplayer.getDefault().setStatusText(""); // NOI18N
        }
        if (settingsListener != null) {
            FormLoaderSettings.getPreferences().removePreferenceChangeListener(settingsListener);
            settingsListener = null;
        }
        assistantView = null;
        formDesigner = null;
        FormEditorSupport fes = formEditorSupport;
        formEditorSupport = null;
        return fes;
    }

    void resetDesigner(boolean reload) {
        boolean selected;
        if (isShowing()) {
            selected = (FormDesigner.getSelectedDesigner() == formDesigner);
        } else {
            selected = false;
            reload = false;
        }

        JToolBar toolbar = formDesigner != null ? formDesigner.getToolBar() : null;
        formEditorSupport = closeDesigner();
        createDesigner();
        if (toolbar != null) { // need to reuse the previous toolbar component (toolbar of MultiViewElement)
            formDesigner.setToolBar(toolbar);
        }

        if (selected) {
            TopComponent activeTC = TopComponent.getRegistry().getActivated();
            if (activeTC == this || (activeTC != null && activeTC.isAncestorOf(this))) {
                formDesigner.componentActivated();
            } else {
                FormDesigner.setSelectedDesigner(formDesigner, true);
            }
        }
        if (reload) {
            componentShowing();
        }
    }

    @Override
    public void componentShowing() { // TODO also used as API to trigger loading or init after reload...
        formDesigner.componentShowing();

        if (!isAncestorOf(formDesigner.getDesignCanvas())) { // designer not yet displayed
            guiInit();
        }

        if (formEditorSupport.isOpened()) {
            FormEditorSupport.checkFormGroupVisibility();
        } else {
            // Form loading phase 1/3.
            if (preLoadTask == null && formEditorSupport.startFormLoading()) {
                preLoadTask = new PreLoadTask(formEditorSupport.getFormEditor());
                FormUtils.getRequestProcessor().post(preLoadTask);
                StatusDisplayer.getDefault().setStatusText(
                    FormUtils.getFormattedBundleString(
                        "FMT_PreparingForm", // NOI18N
                        new Object[] { formEditorSupport.getFormDataObject().getName() }));
            }
        }
    }

    private void guiInit() {
        removeAll();
        JScrollPane scrollPane = new JScrollPane(formDesigner.getDesignCanvas());
        scrollPane.setBorder(null); // disable border, winsys will handle borders itself
        scrollPane.setViewportBorder(null); // disable also GTK L&F viewport border 
        scrollPane.getVerticalScrollBar().setUnitIncrement(5); // Issue 50054
        scrollPane.getHorizontalScrollBar().setUnitIncrement(5);
        add(scrollPane); // if not yet loaded, the canvas shows "Loading"
        setupAssistant(); // if not yet loaded, a blank placeholder panel is used
    }

    @Override
    public UndoRedo getUndoRedo() {
        UndoRedo.Provider provider = getLookup().lookup(UndoRedo.Provider.class);
        return (provider == null) ? UndoRedo.NONE : provider.getUndoRedo();
    }

    private class PreLoadTask implements Runnable {
        private FormEditor formEditor;
        PreLoadTask(FormEditor formEditor) {
            this.formEditor = formEditor;
        }
        @Override
        public void run() {
            long ms = System.currentTimeMillis();
            // Form loading phase 2/3.
            formEditor.loadOnBackground();
            Logger.getLogger(FormEditor.class.getName()).log(Level.FINER, "Opening form time 2: {0}ms", (System.currentTimeMillis()-ms)); // NOI18N

            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    preLoadTask = null; // set back to null in EDT
                    if (formEditorSupport != null) {
                        loadForm();
                    }
                }
            });
        }
    }

    private void loadForm() {
        assert !formEditorSupport.isOpened();
        long ms = System.currentTimeMillis();
        // Form loading phase 3/3.
        if (formEditorSupport.loadOpeningForm()) {
            FormEditorSupport.checkFormGroupVisibility();
            formDesigner.loadingComplete();
            guiInit();

            Logger.getLogger(FormEditor.class.getName()).log(Level.FINER, "Opening form time 3: {0}ms", (System.currentTimeMillis()-ms)); // NOI18N
        }
    }

    @Override
    public void componentHidden() {
        if (formDesigner != null) {
            formDesigner.componentHidden();
        }
        FormEditorSupport.checkFormGroupVisibility();
    }

    @Override
    public void componentActivated() {
        formDesigner.componentActivated();
    }

    @Override
    public void componentDeactivated() {
        if (formDesigner != null) {
            formDesigner.componentDeactivated();
        }
    }

    @Override
    public void requestVisible() {
        if (multiViewObserver != null) {
            multiViewObserver.requestVisible();
        } else {
            super.requestVisible();
        }
    }

    @Override
    public void requestActive() {
        if (multiViewObserver != null) {
            multiViewObserver.requestActive();
        } else {
            super.requestActive();
        }
    }

    @Override
    public CloseOperationState canCloseElement() {
        return formEditorSupport.canCloseElement(multiViewObserver.getTopComponent());
    }

    @Override
    public Action[] getActions() {
        Action[] actions = super.getActions();
        SystemAction fsAction = SystemAction.get(FileSystemAction.class);
        if (!Arrays.asList(actions).contains(fsAction)) {
            Action[] newActions = new Action[actions.length+1];
            System.arraycopy(actions, 0, newActions, 0, actions.length);
            newActions[actions.length] = fsAction;
            actions = newActions;
        }
        return actions;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        return formDesigner.getToolBar();
    }

    @Override
    public JComponent getVisualRepresentation() {
        return this;
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback callback) {
        multiViewObserver = callback;

        // add FormDesigner as a client property so it can be obtained
        // from multiview TopComponent (it is not sufficient to put
        // it into lookup - only content of the lookup of the active
        // element is accessible)
        callback.getTopComponent().putClientProperty("formDesigner", this); // NOI18N

        // needed for deserialization...
        if (formEditorSupport != null) {
            // this is used (or misused?) to obtain the deserialized multiview
            // topcomponent and set it to FormEditorSupport
            formEditorSupport.setTopComponent(callback.getTopComponent());
        }
    }

    private void setupAssistant() {
        if (formEditorSupport.isOpened()) {
            updateAssistant();
            settingsListener = new PreferenceChangeListener() {
                @Override
                public void preferenceChange(PreferenceChangeEvent evt) {
                    if (FormLoaderSettings.PROP_ASSISTANT_SHOWN.equals(evt.getKey())) {
                        updateAssistant();
                    }
                }
            };
            FormLoaderSettings.getPreferences().addPreferenceChangeListener(settingsListener);
        } else if (FormLoaderSettings.getInstance().getAssistantShown()) {
            // only placeholder space during loading
            Component c = new JPanel();
            c.setPreferredSize(new Dimension(10, 41));
            c.setBackground(FormLoaderSettings.getInstance().getFormDesignerBackgroundColor());
            add(c, BorderLayout.NORTH);
        }
    }

    private void updateAssistant() {
        if (FormLoaderSettings.getInstance().getAssistantShown()) {
            AssistantModel assistant = FormEditor.getAssistantModel(formDesigner.getFormModel());
            assistantView = new AssistantView(assistant);
            assistant.setContext("select"); // NOI18N
            add(assistantView, BorderLayout.NORTH);
        } else if (assistantView != null) {
            remove(assistantView);
            assistantView = null;
        }
        revalidate();
        repaint();
    }

    private static class FormDesignerLookup extends ProxyLookup {
        void setLookupFromDesigner(FormDesigner designer) {
            setLookups(designer.getLookup());
        }
    }
}
