/*
 * 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.test.ide;

import com.sun.management.HotSpotDiagnosticMXBean;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import org.netbeans.api.java.source.ui.ScanDialog;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.junit.Log;
import org.openide.cookies.EditorCookie;
import org.openide.explorer.view.TreeView;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.windows.TopComponent;

/**
 *
 * @author Jaroslav Tulach <jtulach@netbeans.org>
 */
public final class WatchProjects {
    private static Logger LOG = Logger.getLogger(WatchProjects.class.getName());


    private WatchProjects() {
    }

    public static void initialize() throws Exception {
        Log.enableInstances(Logger.getLogger("TIMER"), "Project", Level.FINEST);

    }

    private static void cleanWellKnownStaticFields() throws Exception {
        Object o;

//        resetJTreeUIs(Frame.getFrames());

        tryCloseNavigator();

        StringSelection ss = new StringSelection("");
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
//      Toolkit.getDefaultToolkit().getSystemSelection().setContents(ss, ss);
//      fix for Issue 146901
        Clipboard clipBoard = Toolkit.getDefaultToolkit().getSystemSelection();
        if (clipBoard != null) {
            clipBoard.setContents(ss, ss);
        }
        Clipboard cc = Lookup.getDefault().lookup(Clipboard.class);
        Assert.assertNotNull("There is a clipboard in lookup", cc);
        cc.setContents(ss, ss);

        for (Frame f : Frame.getFrames()) {
            clearInstanceField( f, "java.awt.Container", "dispatcher" );
        }

// XXX: uncommented because of the csl.api & related changes
        JFrame empty = new JFrame("Clear");
        empty.getContentPane().setLayout(new FlowLayout());
        empty.getContentPane().add(new JEditorPane());
        empty.pack();
        empty.setVisible(true);
        empty.requestFocusInWindow();
// --------------------------------------------------------


        clearField("sun.awt.im.InputContext", "previousInputMethod");
        clearField("sun.awt.im.InputContext", "inputMethodWindowContext");
        clearField("sun.awt.im.CompositionAreaHandler", "compositionAreaOwner");
//        clearField("sun.awt.AppContext", "mainAppContext");
//        clearField("org.netbeans.modules.beans.BeanPanel", "INSTANCE");
        clearField("java.awt.KeyboardFocusManager", "focusedWindow");
        clearField("java.awt.KeyboardFocusManager", "activeWindow");
        clearField("java.awt.KeyboardFocusManager", "focusOwner");
        clearField("java.awt.KeyboardFocusManager", "permanentFocusOwner");
        clearField("java.awt.KeyboardFocusManager", "newFocusOwner");
        clearField("java.awt.KeyboardFocusManager", "currentFocusCycleRoot");
//        clearField("org.netbeans.jemmy.EventTool", "listenerSet");
        clearField("sun.awt.X11.XKeyboardFocusManagerPeer", "currentFocusOwner");
        clearField("sun.awt.X11.XKeyboardFocusManagerPeer", "currentFocusedWindow");
//        clearField("org.netbeans.modules.java.navigation.CaretListeningFactory", "INSATNCE");
//        clearField("org.netbeans.modules.editor.hints.HintsUI", "INSTANCE");
//        clearField("org.netbeans.modules.websvc.core.ProjectWebServiceView", "views");
//        clearField("org.netbeans.api.java.source.support.OpenedEditors", "DEFAULT");
//        clearField("org.netbeans.spi.palette.PaletteSwitch", "theInstance");
//        clearField("org.netbeans.core.NbMainExplorer$MainTab", "lastActivated");
//        clearField("org.netbeans.core.NbMainExplorer$MainTab", "DEFAULT");
/*
        o = getFieldValue("org.netbeans.api.java.source.JavaSource", "toRemove");
        if (o instanceof Collection) {
            Collection c = (Collection) o;
            c.clear();
        }
        o = getFieldValue("org.netbeans.api.java.source.JavaSource", "requests");
        if (o instanceof Collection) {
            Collection c = (Collection) o;
            c.clear();
        }
*/
        clearField("sun.awt.im.InputContext", "previousInputMethod");
        clearField("sun.awt.im.InputContext", "inputMethodWindowContext");
    }


    public static void assertTextDocuments() throws Exception {
        for (TopComponent tc : new ArrayList<TopComponent>(TopComponent.getRegistry().getOpened())) {
            final EditorCookie ec = tc.getLookup().lookup(EditorCookie.class);
            if (ec != null) {
                ec.close();
            }
        }
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                TopComponent tc = new TopComponent();
                tc.setLayout(new FlowLayout());
                tc.add(new JTextArea());
                tc.open();
                tc.requestVisible();
                tc.requestActive();
                String jVMversion = System.getProperty("java.specification.version");
                System.out.println("Java.specification.version="+jVMversion);
                if (!("1.8".equals(jVMversion))) {
                    try {
                        System.out.println("Cleaning well known static fields");
                        cleanWellKnownStaticFields();
                    } catch (Exception ex) {
                        throw new IllegalStateException(ex);
                    }
                }
                System.setProperty("assertgc.paths", "5");
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException exc) {
                    Exceptions.printStackTrace(exc);
                }
                try {
                    Log.assertInstances("Are all documents GCed?", "TextDocument");
                } finally {
                    dumpHeap(null);
                }
            }
        });
    }

    public static void assertProjects() throws Exception {
        Object o;

        OpenProjects.getDefault().close(
            OpenProjects.getDefault().getOpenProjects()
        );
        Project p = new Project() {
            public FileObject getProjectDirectory() {
                return FileUtil.getConfigRoot();
            }

            public Lookup getLookup() {
                return Lookup.EMPTY;
            }
        };
        try {
            OpenProjects.getDefault().open(new Project[] { p }, false);
        } catch (AssertionError ae) {
            System.out.println("Excepton during creation of fake project:");
            ae.printStackTrace();
        }
        try {
            OpenProjects.getDefault().setMainProject(p);
        } catch (AssertionError ae) {
            System.out.println("Excepton during setting of fake project as main:");
            ae.printStackTrace();
        }

        for (int i = 0; i < 10; i++) {
            EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        Exceptions.printStackTrace(ex);
                    }
            }
        });
        }

        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                try {
                    cleanWellKnownStaticFields();
                } catch (Exception ex) {
                    throw new IllegalStateException(ex);
                }
                if (Boolean.getBoolean("ignore.random.failures")) {
                    // remove the if we don't care about random failures
                    // reported as #
                    //removeTreeView(Frame.getFrames());
                }

                System.setProperty("assertgc.paths", "5");
                try {
                    Log.assertInstances("Checking if all projects are really garbage collected", "Project");
                } catch (AssertionFailedError t) {
                    Logger.getLogger(WatchProjects.class.getName()).warning(t.getMessage());
                    if (!Boolean.getBoolean("ignore.random.failures")) {
                        throw t;
                    }
                } finally {
                    dumpHeap(null);
                    try {
                        Thread.sleep(4000);
                    } catch (InterruptedException exc) {
                        Exceptions.printStackTrace(exc);
                    }
                    try {
                        printTreeView(Frame.getFrames());
                    } catch (Exception ex) {
                        throw new IllegalStateException(ex);
                    }
                }
            }
        });
    }

    private static int printTreeView(Component[] arr) throws Exception {
        int cnt = 0;
        StringBuilder str = new StringBuilder();
        for (Component c : arr) {
            if (c instanceof TreeView) {
                Set<?> set = (Set<?>) getField(TreeView.class, "visHolder").get(c);
                if (!set.isEmpty()) {
                    cnt += set.size();
                    str.append("visHolder for TreeView in '" + c.getParent().getName() + "':");
                    for (Object o : set) {
                        str.append(o);
                    }
                }
                continue;
            }
            if (c instanceof Container) {
                Container o = (Container)c;
                cnt += printTreeView(o.getComponents());
            }
        }
        if (str.length() > 0) {
            Logger.getLogger(WatchProjects.class.getName()).warning(str.toString());
        }
        return cnt;
    }

    private static void removeTreeView(Component[] arr) throws Exception {
        for (Component c : arr) {
            if (c instanceof TreeView) {
                Set<?> set = (Set<?>) getField(TreeView.class, "visHolder").get(c);
                set.clear();
                continue;
            }
            if (c instanceof Container) {
                Container o = (Container)c;
                removeTreeView(o.getComponents());
            }
        }
    }
    private static void resetJTreeUIs(Component[] arr) {
        for (Component c : arr) {
            if (c instanceof JTree) {
                JTree jt = (JTree)c;
                jt.updateUI();
            }
            if (c instanceof Container) {
                Container o = (Container)c;
                resetJTreeUIs(o.getComponents());
            }
        }
    }

    /**
     * #124061 workaround - close navigator before tests
     */
    private static void tryCloseNavigator() throws Exception {
        for (TopComponent c : new ArrayList<TopComponent>(TopComponent.getRegistry().getOpened())) {
            LOG.fine("Processing TC " + c.getDisplayName() + "class " + c.getClass().getName());
            if (c.getClass().getName().equals("org.netbeans.modules.navigator.NavigatorTC")) {
                final TopComponent navigator = c;
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        navigator.close();
                    }
                });
                LOG.fine("tryCloseNavigator: Navigator closed, OK!");
                break;
            }
        }
        clearField("org.netbeans.modules.navigator.NavigatorTC", "instance");
        clearField("org.netbeans.modules.navigator.ProviderRegistry","instance");
    }

    private static Object clearField(String clazz, String... name) throws Exception {
        return clearInstanceField(null, clazz, name);
    }
    private static Object getFieldValue(String clazz, String... name) throws Exception {
        Object ret = null;
        for (int i = 0; i < name.length; i++) {
            Field f = i == 0 ? getField(clazz, name[0]) : getField(ret.getClass(), name[i]);
            ret = f.get(ret);
        }
        return ret;
    }


    private static Field getField(String clazz, String name) throws NoSuchFieldException, ClassNotFoundException {
        ClassLoader l = Thread.currentThread().getContextClassLoader();
        if (l == null) {
            l = WatchProjects.class.getClassLoader();
        }
        Class<?> c = Class.forName(clazz, true, l);
        return getField(c, name);
    }
    private static Field getField(Class<?> clazz, String name) throws NoSuchFieldException {
        Field f = clazz.getDeclaredField(name);
        f.setAccessible(true);
        return f;
    }

    private static Object clearInstanceField(Object obj, String clazz, String... name) throws Exception {
        Object ret = obj;
        for (int i = 0; i < name.length; i++) {
            Field f;
            try {
                f = i == 0 ? getField(clazz, name[0]) : getField(ret.getClass(), name[i]);
            } catch (NoSuchFieldException ex) {
                LOG.log(Level.WARNING, "Cannot get " + name[i]);
                continue;
            } catch (ClassNotFoundException ex) {
                LOG.log(Level.WARNING, "Cannot class " + clazz);
                continue;
            }
            Object now = ret;
            ret = f.get(now);
            for (int tryHarder = 0;; tryHarder++) {
                f.set(now, null);
                if (f.get(now) == null) {
                    break;
                }
                if (tryHarder == 10) {
                    Assert.fail("Field is really cleared " + f + " but was: " + f.get(now));
                }
                Thread.sleep(100);
            }
            if (ret == null) {
                LOG.info("Getting " + f + " from " + now + " returned null");
                break;
            }
        }
        return ret;
    }

    private static void dumpHeap(String path) {
        System.out.println("DUMPING HEAP");
        Method m = null;
        Class c = null;
        HotSpotDiagnosticMXBean hdmxb=null;
        try {
            c = Class.forName("sun.management.ManagementFactoryHelper");//NOI18N
        } catch (ClassNotFoundException exc) {
            System.out.println(exc.getMessage());
            try {
                c = Class.forName("sun.management.ManagementFactory");//NOI18N
            } catch (ClassNotFoundException ex1) {
                System.out.println(ex1.getMessage());
            }
        }
        if (c!=null) {
            try {
                m= c.getMethod("getDiagnosticMXBean");//NOI18N
            } catch (NoSuchMethodException exc) {
                System.out.println(exc.getMessage());
            } catch (SecurityException exc) {
                System.out.println(exc.getMessage());
            }
        }
        if (m!=null) {
            try {
                hdmxb= (HotSpotDiagnosticMXBean)m.invoke(null);
            } catch (IllegalAccessException ex) {
                Exceptions.printStackTrace(ex);
            } catch (IllegalArgumentException ex) {
                Exceptions.printStackTrace(ex);
            } catch (InvocationTargetException ex) {
                Exceptions.printStackTrace(ex);
            }
            long i = System.currentTimeMillis();
            if (path==null || "".equals(path)) {
                path=System.getProperty("nbjunit.workdir")+File.separator+"Heapdump"+i+".hprof";
            }
            System.out.println("Creating heap dump, target directory="+path);
            try {
                hdmxb.dumpHeap(path, true);
                System.out.println("Heap dump successfully created in: "+path);
            } catch (IOException ioe) {
                System.out.println(ioe.getMessage());
            }
        }
    }

    public static void waitScanFinished() {
        try {
            class Wait implements Runnable {

                boolean initialized;
                boolean ok;

                public void run() {
                    if (initialized) {
                        ok = true;
                        return;
                    }
                    initialized = true;
                    boolean canceled = ScanDialog.runWhenScanFinished(this, "tests");
                    Assert.assertFalse("Dialog really finished", canceled);
                    Assert.assertTrue("Runnable run", ok);
                }
            }
            Wait wait = new Wait();
            SwingUtilities.invokeAndWait(wait);
        } catch (Exception ex) {
            throw (AssertionFailedError)new AssertionFailedError().initCause(ex);
        }
    }
}
