param(
    [string]$Title = "Διάλεξε φωτογραφίες",
    [string]$OutFile = "",
    [string]$Start = "",
    [string]$Owner = "0"
)

$ErrorActionPreference = "Stop"
[Console]::OutputEncoding = [Text.UTF8Encoding]::new()

function Write-PickResult([string[]]$paths) {
    $json = ConvertTo-Json -Compress @($paths)
    if ($OutFile -ne "") {
        [IO.File]::WriteAllText($OutFile, $json, [Text.UTF8Encoding]::new($false))
    } else {
        [Console]::Out.Write($json)
    }
}

if (-not ("LabVistaImagePicker" -as [type])) {
    Add-Type -TypeDefinition @"
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public static class LabVistaImagePicker {
    [ComImport]
    [Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")]
    private class FileOpenDialog {}

    [ComImport]
    [Guid("d57c7288-d4ad-4768-be02-9d969532d960")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IFileOpenDialog {
        [PreserveSig] int Show(IntPtr parent);
        void SetFileTypes(uint cFileTypes, IntPtr rgFilterSpec);
        void SetFileTypeIndex(uint iFileType);
        void GetFileTypeIndex(out uint piFileType);
        void Advise(IntPtr pfde, out uint pdwCookie);
        void Unadvise(uint dwCookie);
        void SetOptions(uint fos);
        void GetOptions(out uint pfos);
        void SetDefaultFolder(IShellItem psi);
        void SetFolder(IShellItem psi);
        void GetFolder(out IShellItem ppsi);
        void GetCurrentSelection(out IShellItem ppsi);
        void SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
        void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
        void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
        void SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
        void SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
        void GetResult(out IShellItem ppsi);
        void AddPlace(IShellItem psi, int fdap);
        void SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
        void Close(int hr);
        void SetClientGuid(ref Guid guid);
        void ClearClientData();
        void SetFilter(IntPtr pFilter);
        void GetResults(out IShellItemArray ppenum);
        void GetSelectedItems(out IShellItemArray ppsai);
    }

    [ComImport]
    [Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellItem {
        void BindToHandler(IntPtr pbc, ref Guid bhid, ref Guid riid, out IntPtr ppv);
        void GetParent(out IShellItem ppsi);
        void GetDisplayName(uint sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
        void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
        void Compare(IShellItem psi, uint hint, out int piOrder);
    }

    [ComImport]
    [Guid("b63ea76d-1f85-456f-a19c-48159efa858b")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellItemArray {
        void BindToHandler(IntPtr pbc, ref Guid bhid, ref Guid riid, out IntPtr ppv);
        void GetPropertyStore(int flags, ref Guid riid, out IntPtr ppv);
        void GetPropertyDescriptionList(IntPtr keyType, ref Guid riid, out IntPtr ppv);
        void GetAttributes(int attribFlags, uint sfgaoMask, out uint psfgaoAttribs);
        void GetCount(out uint pdwNumItems);
        void GetItemAt(uint dwIndex, out IShellItem ppsi);
        void EnumItems(out IntPtr ppenumShellItems);
    }

    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHCreateItemFromParsingName(
        [MarshalAs(UnmanagedType.LPWStr)] string pszPath,
        IntPtr pbc,
        [In] ref Guid riid,
        [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);

    private const uint FOS_ALLOWMULTISELECT = 0x00000200;
    private const uint FOS_FORCEFILESYSTEM = 0x00000040;
    private const uint FOS_FILEMUSTEXIST = 0x00001000;
    private const uint FOS_PATHMUSTEXIST = 0x00000800;
    private const uint SIGDN_FILESYSPATH = 0x80058000;

    public static string[] Pick(string title, string start, long owner) {
        var dlg = (IFileOpenDialog)new FileOpenDialog();
        uint options;
        dlg.GetOptions(out options);
        dlg.SetOptions(options | FOS_ALLOWMULTISELECT | FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST);
        if (!string.IsNullOrEmpty(title)) {
            dlg.SetTitle(title);
        }
        if (!string.IsNullOrEmpty(start)) {
            try {
                Guid iid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE");
                IShellItem folder;
                if (SHCreateItemFromParsingName(start, IntPtr.Zero, ref iid, out folder) == 0 && folder != null) {
                    dlg.SetFolder(folder);
                }
            } catch {}
        }
        IntPtr hwnd = owner == 0 ? IntPtr.Zero : new IntPtr(owner);
        int hr = dlg.Show(hwnd);
        if (hr != 0) {
            return new string[0];
        }
        IShellItemArray arr;
        dlg.GetResults(out arr);
        uint count;
        arr.GetCount(out count);
        var list = new List<string>();
        for (uint i = 0; i < count; i++) {
            IShellItem item;
            arr.GetItemAt(i, out item);
            string path;
            item.GetDisplayName(SIGDN_FILESYSPATH, out path);
            if (!string.IsNullOrEmpty(path)) {
                list.Add(path);
            }
        }
        return list.ToArray();
    }
}
"@
}

$hwnd = [int64]0
if ($Owner -ne "" -and $Owner -ne "0") {
    try { $hwnd = [int64]$Owner } catch { $hwnd = 0 }
}

try {
    $paths = [LabVistaImagePicker]::Pick($Title, $Start, $hwnd)
    if ($paths -and $paths.Count -gt 0) {
        Write-PickResult @($paths)
        exit 0
    }
    Write-PickResult @()
    exit 0
} catch {}

Add-Type -AssemblyName System.Windows.Forms
$d = New-Object System.Windows.Forms.OpenFileDialog
$d.Title = $Title
$d.Filter = "Φωτογραφίες|*.jpg;*.jpeg;*.png;*.webp;*.JPG;*.JPEG;*.PNG;*.WEBP|Όλα|*.*"
$d.Multiselect = $true
$d.CheckFileExists = $true
$d.RestoreDirectory = $true
if ($Start -ne "" -and (Test-Path -LiteralPath $Start)) { $d.InitialDirectory = $Start }
$names = @()
if ($d.ShowDialog() -eq [Windows.Forms.DialogResult]::OK) {
    $names = @($d.FileNames)
}
Write-PickResult $names
