/*
 * Copyright 2013-2016 consulo.io
 *
 * 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 consulo.unity3d.run.debugger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.Icon;

import com.intellij.ide.util.ChooseElementsDialog;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.ui.UIUtil;
import com.jezhumble.javasysmon.JavaSysMon;
import com.jezhumble.javasysmon.ProcessInfo;
import consulo.awt.TargetAWT;
import consulo.unity3d.Unity3dIcons;

/**
 * @author VISTALL
 * @since 18.11.14
 */
public class UnityProcessDialog extends ChooseElementsDialog<UnityProcess>
{
	private static final Logger LOGGER = Logger.getInstance(UnityProcessDialog.class);

	private Future<?> myTask;

	public UnityProcessDialog(@Nonnull Project project)
	{
		super(project, new ArrayList<>(), "Select Unity Process", "", true);
	}

	@Override
	public void show()
	{
		myTask = AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay((Runnable) () ->
		{
			List<UnityProcess> elements = collectItems();

			UIUtil.invokeLaterIfNeeded(() ->
			{
				List<UnityProcess> selectedElements = myChooser.getSelectedElements();
				setElements(elements, selectedElements);
			});
		}, 0, 1, TimeUnit.SECONDS);
		super.show();
	}

	@Nonnull
	public static List<UnityProcess> collectItems()
	{
		Collection<UnityPlayer> players = UnityPlayerService.getInstance().getPlayers();
		List<UnityProcess> items = new ArrayList<>(players.size() + 1);
		try
		{
			for(UnityPlayer player : players)
			{
				if(player.isSupportDebugging())
				{
					items.add(new UnityProcess((int) player.getGuid(), player.getId(), player.getIp(), player.getDebuggerPort()));
				}
			}
			JavaSysMon javaSysMon = new JavaSysMon();
			ProcessInfo[] processInfos = javaSysMon.processTable();
			for(ProcessInfo processInfo : processInfos)
			{
				String name = processInfo.getName();

				if(StringUtil.startsWithIgnoreCase(name, "unity") || StringUtil.containsIgnoreCase(name, "Unity.app"))
				{
					// ignore 'UnityHelper' and 'Unity Helper'
					if(StringUtil.containsIgnoreCase(name, "Unity") && StringUtil.containsIgnoreCase(name, "Helper"))
					{
						continue;
					}

					// UnityShader - Package Manager - Hub compiler
					if(StringUtil.containsIgnoreCase(name, "UnityShader") || StringUtil.containsIgnoreCase(name, "UnityPackageMan") || StringUtil.containsIgnoreCase(name, "unityhub"))
					{
						continue;
					}

					items.add(new UnityProcess(processInfo.getPid(), name, "localhost", buildDebuggerPort(processInfo.getPid())));
				}
			}
		}
		catch(Exception e)
		{
			LOGGER.error(e);
		}
		return items;
	}

	public static int buildDebuggerPort(int pid)
	{
		return 56000 + pid % 1000;
	}

	@Nullable
	@Override
	protected String getDimensionServiceKey()
	{
		return getClass().getSimpleName();
	}

	@Override
	protected void dispose()
	{
		if(myTask != null)
		{
			myTask.cancel(false);
		}
		super.dispose();
	}

	@Override
	protected String getItemText(UnityProcess item)
	{
		return item.getName() + " (" + item.getHost() + ":" + item.getPort() + ")";
	}

	@Nullable
	@Override
	protected Icon getItemIcon(UnityProcess item)
	{
		return TargetAWT.to(Unity3dIcons.Unity3d);
	}
}

@@ -1119,24 +1119,75 @@
 ecutorUtil;%0A
+import com.intellij.util.containers.ContainerUtil;%0A
 import com.i
@@ -2770,16 +2770,416 @@
 ame();%0A%0A
+%09%09%09%09// Unity 2019.3 linux bug - 2020.1 ok%0A%09%09%09%09if(name.equals(%22Main%22))%0A%09%09%09%09%7B%0A%09%09%09%09%09List%3CString%3E list = StringUtil.split(processInfo.getCommand(), %22 %22);%0A%09%09%09%09%09String first = ContainerUtil.getFirstItem(list);%0A%09%09%09%09%09if(first != null && first.endsWith(%22/Editor/Unity%22))%0A%09%09%09%09%09%7B%0A%09%09%09%09%09%09items.add(new UnityProcess(processInfo.getPid(), name, %22localhost%22, buildDebuggerPort(processInfo.getPid())));%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%0A
 %09%09%09%09if(S

fix bug from https://discuss.consulo.io/t/consulo-and-unity-with-linux/234/9