/*
 * Copyright 2003-2015 Yusuke Yamamoto
 *
 * 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 samurai.swing;

import com.sun.tools.attach.AttachNotSupportedException;
import samurai.remotedump.ProcessUtil;
import samurai.remotedump.ThreadDumpUtil;
import samurai.remotedump.VM;
import samurai.util.Configuration;
import sun.jvmstat.monitor.MonitorException;

import javax.swing.*;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class LocalProcesses {
    private final FileHistory fileHistory;
    private final JMenu localProcessesMenu;

    public LocalProcesses(Configuration config, FileHistory fileHistory) {
        config.apply(this);
        this.fileHistory = fileHistory;
        localProcessesMenu = new JMenu();
        localProcessesMenu.addMenuListener(new MenuListener() {
            @Override
            public void menuSelected(MenuEvent e) {
                updateChildMenuItems();
            }

            @Override
            public void menuDeselected(MenuEvent e) {

            }

            @Override
            public void menuCanceled(MenuEvent e) {

            }
        });
//        updateChildMenuItems();
    }

    public JMenu getLocalProcessesMenu() {
        return this.localProcessesMenu;
    }

    private void updateChildMenuItems() {
        try {
            List<VM> currentVms = ProcessUtil.getVMs("localhost");

            for (int i = 0; i < localProcessesMenu.getItemCount(); i++) {
                LocalProcessMenuItem item = (LocalProcessMenuItem) localProcessesMenu.getItem(i);
                boolean found = false;
                for (VM vm : currentVms) {
                    if (item.getVm().getPid() == vm.getPid()) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    localProcessesMenu.remove(item);
                }

            }

            for (VM vm : currentVms) {
                boolean found = false;
                for (int i = 0; i < localProcessesMenu.getItemCount(); i++) {
                    LocalProcessMenuItem item = (LocalProcessMenuItem) localProcessesMenu.getItem(i);
                    if (item.getVm().getPid() == vm.getPid()) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    JMenuItem localProcess = new LocalProcessMenuItem(vm);
                    localProcess.setToolTipText(vm.getFullCommandLine());
                    localProcessesMenu.add(localProcess);
                }
            }
        } catch (URISyntaxException | MonitorException e) {
            e.printStackTrace();
        }
    }

    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");

    class LocalProcessMenuItem extends JMenuItem {
        final VM vm;

        public LocalProcessMenuItem(VM vm) {
            super(String.format("%s %s", vm.getPid(), vm.getFqcn()));
            this.vm = vm;
            addActionListener(e -> {
                try {
                    Path path = Paths.get(System.getProperty("user.home"),
                            String.format("%s-%d-%s.txt", vm.getFqcn(), vm.getPid(), LocalDateTime.now().format(dateTimeFormatter)));
                    for (int i = 0; i < 3; i++) {
                        Files.write(path, ThreadDumpUtil.getThreadDump(vm.getPid()), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
                        fileHistory.open(path.toFile());
                        Thread.sleep(1000);
                    }
                } catch (InterruptedException | AttachNotSupportedException | IOException e1) {
                    e1.printStackTrace();
                }
            });
        }

        public VM getVm() {
            return vm;
        }

    }
}

@@ -1024,32 +1024,74 @@
 yntaxException;%0A
+import java.nio.charset.StandardCharsets;%0A
 import java.nio.
@@ -1195,16 +1195,100 @@
 il.List;
+%0Aimport java.util.concurrent.ExecutorService;%0Aimport java.util.concurrent.Executors;
 %0A%0Apublic
@@ -1974,42 +1974,8 @@
 %7D);%0A
-//        updateChildMenuItems();%0A
     
@@ -3669,54 +3669,194 @@
     
-class LocalProcessMenuItem extends JMenuItem %7B
+ExecutorService executor = Executors.newFixedThreadPool(1);%0A%0A    class LocalProcessMenuItem extends JMenuItem %7B%0A        private static final long serialVersionUID = 2629440395264682598L;
 %0A   
@@ -4049,16 +4049,39 @@
 ner(e -%3E
+ executor.execute(() -%3E
  %7B%0A     
@@ -4302,24 +4302,714 @@
 rmatter)));%0A
+                    Files.writeString(path, LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + %22%5Cn%22, StandardOpenOption.CREATE, StandardOpenOption.APPEND);%0A                    Files.writeString(path, %22pid: %22 + vm.getPid() + %22%5Cn%5Cn%22, StandardOpenOption.CREATE, StandardOpenOption.APPEND);%0A                    Files.writeString(path, %22FQCN: %22 + vm.getFqcn() + %22%5Cn%5Cn%22, StandardOpenOption.CREATE, StandardOpenOption.APPEND);%0A                    Files.writeString(path, String.format(%22Command line:%5Cn%25s%5Cn%5Cn%22, vm.getFullCommandLine()), StandardOpenOption.CREATE, StandardOpenOption.APPEND);%0A%0A                    SwingUtilities.invokeLater(() -%3E fileHistory.open(path.toFile()));%0A%0A
             
@@ -5190,65 +5190,8 @@
 D);%0A
-                        fileHistory.open(path.toFile());%0A
     
@@ -5418,24 +5418,25 @@
           %7D)
+)
 ;%0A        %7D%0A

Make local process thread dump taking action asynchronous