/*
 * Copyright 2013-2017 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.packages;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import consulo.disposer.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.sun.jna.platform.win32.Guid;
import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.Shell32Util;
import com.sun.jna.platform.win32.ShlObj;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.PointerByReference;

/**
 * @author VISTALL
 * @since 20-Oct-17
 */
@Singleton
public class Unity3dPackageWatcher implements Disposable
{
	@Nonnull
	public static Unity3dPackageWatcher getInstance()
	{
		return Application.get().getComponent(Unity3dPackageWatcher.class);
	}

	private final LocalFileSystem myLocalFileSystem;

	private Set<LocalFileSystem.WatchRequest> myWatchRequests = Collections.emptySet();

	private final List<String> myPackageDirPaths;

	@Inject
	public Unity3dPackageWatcher(VirtualFileManager virtualFileManager)
	{
		myLocalFileSystem = LocalFileSystem.get(virtualFileManager);

		myPackageDirPaths = convertUserPathToPackagePaths();

		if(myPackageDirPaths.isEmpty())
		{
			return;
		}

		myWatchRequests = myLocalFileSystem.addRootsToWatch(myPackageDirPaths, true);
	}

	@Nonnull
	public List<String> getPackageDirPaths()
	{
		return myPackageDirPaths;
	}

	@Override
	public void dispose()
	{
		myLocalFileSystem.removeWatchedRoots(myWatchRequests);
	}

	@Nonnull
	private List<String> convertUserPathToPackagePaths()
	{
		return getUnityUserPaths().stream().map(path -> FileUtil.toSystemIndependentName(path) + "/cache/packages/packages.unity.com/").collect(Collectors.toList());
	}

	@Nonnull
	private static List<String> getUnityUserPaths()
	{
		List<String> paths = new SmartList<>();
		if(SystemInfo.isWinVistaOrNewer)
		{
			paths.add(Shell32Util.getFolderPath(ShlObj.CSIDL_LOCAL_APPDATA) + "\\Unity");

			PointerByReference pointerByReference = new PointerByReference();
			// LocalLow
			WinNT.HRESULT hresult = Shell32.INSTANCE.SHGetKnownFolderPath(Guid.GUID.fromString("{A520A1A4-1780-4FF6-BD18-167343C5AF16}"), 0, null, pointerByReference);

			if(hresult.longValue() == 0)
			{
				paths.add(pointerByReference.getValue().getWideString(0) + "\\Unity");
			}
		}
		else if(SystemInfo.isMac)
		{
			paths.add(SystemProperties.getUserHome() + "/Library/Unity");
		}
		else if(SystemInfo.isLinux)
		{
			paths.add(SystemProperties.getUserHome() + "/.config/unity3d");
		}

		return paths;
	}
}

@@ -635,342 +635,52 @@
 ort 
-java.util.Collections;%0Aimport java.util.List;%0Aimport java.util.Set;%0Aimport java.util.stream.Collectors;%0A%0Aimport javax.annotation.Nonnull;%0Aimport jakarta.inject.Inject;%0Aimport jakarta.inject.Singleton;%0A%0Aimport consulo.disposer.Disposable;%0Aimport com.intellij.openapi.application.Application;%0Aimport com.intellij.openapi.util.SystemInfo
+com.intellij.openapi.application.Application
 ;%0Aim
@@ -828,44 +828,8 @@
 er;%0A
-import com.intellij.util.SmartList;%0A
 impo
@@ -901,20 +901,17 @@
 m.win32.
-Guid
+*
 ;%0Aimport
@@ -928,202 +928,335 @@
 na.p
-latform.win32.Shell32;%0Aimport com.sun.jna.platform.win32.Shell32Util;%0Aimport com.sun.jna.platform.win32.ShlObj;%0Aimport com.sun.jna.platform.win32.WinNT;%0Aimport com.sun.jna.ptr.PointerByReference
+tr.PointerByReference;%0Aimport consulo.disposer.Disposable;%0Aimport consulo.platform.Platform;%0Aimport jakarta.inject.Inject;%0Aimport jakarta.inject.Singleton;%0A%0Aimport javax.annotation.Nonnull;%0Aimport java.util.ArrayList;%0Aimport java.util.Collections;%0Aimport java.util.List;%0Aimport java.util.Set;%0Aimport java.util.stream.Collectors
 ;%0A%0A/
@@ -2542,13 +2542,13 @@
 new 
-Smart
+Array
 List
@@ -2557,29 +2557,156 @@
 ();%0A
+%0A
 %09%09
-if(SystemInfo
+Platform platform = Platform.current();%0A%09%09Platform.OperatingSystem os = platform.os();%0A%09%09Platform.User user = platform.user();%0A%0A%09%09if(os
 .isWin
+dows
 Vist
@@ -2713,16 +2713,18 @@
 aOrNewer
+()
 )%0A%09%09%7B%0A%09%09
@@ -3182,24 +3182,18 @@
  if(
-SystemInf
 o
+s
 .isMac
+()
 )%0A%09%09
@@ -3211,36 +3211,24 @@
 add(
-SystemProperties.getUserHome
+user.getHomePath
 () +
@@ -3265,26 +3265,18 @@
  if(
-SystemInf
 o
+s
 .isLinux
 )%0A%09%09
@@ -3271,16 +3271,18 @@
 .isLinux
+()
 )%0A%09%09%7B%0A%09%09
@@ -3296,36 +3296,24 @@
 add(
-SystemProperties.getUserHome
+user.getHomePath
 () +

use homepath