#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import pickle
import sys
from ctypes import pointer
from gi.repository import GLib

if sys.platform != 'win32':
    import fcntl

n_version = "7.8.0"
t_version = "v" + n_version
t_title = 'Tauon'
t_id = 'tauonmb'
t_agent = "TauonMusicBox/" + n_version


print(f"{t_title} {t_version}")
print('Copyright 2015-2023 Taiko2k captain.gxj@gmail.com\n')

# Early arg processing
def transfer_args_and_exit():
    import urllib.request
    base = "http://localhost:7813/"

    if len(sys.argv) <= 1:
        url = base + "raise/"
        urllib.request.urlopen(url)

    for item in sys.argv:

        if not item.endswith(".py") and not item.startswith("-") and not item.endswith("exe") and (item.startswith("file://") or os.path.exists(item)):
            import base64
            url = base + "open/" + base64.urlsafe_b64encode(item.encode()).decode()
            urllib.request.urlopen(url)
        if item == "--play-pause":
            url = base + "playpause/"
            urllib.request.urlopen(url)
        if item == "--play":
            url = base + "play/"
            urllib.request.urlopen(url)
        if item == "--pause":
            url = base + "pause/"
            urllib.request.urlopen(url)
        if item == "--stop":
            url = base + "stop/"
            urllib.request.urlopen(url)
        if item == "--next":
            url = base + "next/"
            urllib.request.urlopen(url)
        if item == "--previous":
            url = base + "previous/"
            urllib.request.urlopen(url)
        if item == "--shuffle":
            url = base + "shuffle/"
            urllib.request.urlopen(url)
        if item == "--repeat":
            url = base + "repeat/"
            urllib.request.urlopen(url)

    sys.exit()


if "--no-start" in sys.argv:
    transfer_args_and_exit()

install_directory = os.path.dirname(os.path.abspath(__file__))

pyinstaller_mode = False
if hasattr(sys, "_MEIPASS"):
    pyinstaller_mode = True
if install_directory.endswith("\\_internal"):
    pyinstaller_mode = True
    install_directory = os.path.dirname(install_directory)

if pyinstaller_mode:
     os.environ["PATH"] += ":" + sys._MEIPASS
     os.environ['SSL_CERT_FILE'] = os.path.join(install_directory, "certifi", "cacert.pem")

# If we're installed, use home data locations
install_mode = False
if install_directory.startswith("/opt/")\
        or install_directory.startswith("/usr/")\
        or install_directory.startswith("/app/")\
        or install_directory.startswith("/snap/") or sys.platform == "darwin" or sys.platform == 'win32':
    install_mode = True

# Assume that it's a classic Linux install, use standard paths
if install_directory.startswith("/usr/"):
    install_directory = "/usr/share/TauonMusicBox"

user_directory = os.path.join(install_directory, "user-data")
config_directory = user_directory
asset_directory = os.path.join(install_directory, "assets")

if install_directory.startswith("/app/"):
    # Its Flatpak
    t_id = "com.github.taiko2k.tauonmb"
os.environ["SDL_VIDEO_WAYLAND_WMCLASS"] = t_id
os.environ["SDL_VIDEO_X11_WMCLASS"] = t_id

if os.path.isfile(os.path.join(install_directory, "portable")):
    install_mode = False

if install_mode:
    user_directory = os.path.join(GLib.get_user_data_dir(), "TauonMusicBox")
if not os.path.isdir(user_directory):
    os.makedirs(user_directory)

fp = None
dev_mode = os.path.isfile(os.path.join(install_directory, '.dev'))
if dev_mode:
    print("Dev mode, ignoring single instancing")
elif sys.platform != 'win32':
    pid_file = os.path.join(user_directory, 'program.pid')
    fp = open(pid_file, 'w')
    try:
        fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except IOError:
        # another instance is running
        print("Program is already running")
        transfer_args_and_exit()
else:
    if sys.platform == "win32":
        pid_file = os.path.join(user_directory, 'program.pid')
        try:
            if os.path.isfile(pid_file):
                os.remove(pid_file)
            fp = open(pid_file, 'w')
        except IOError:
            # another instance is running
            print("Program is already running")
            transfer_args_and_exit()
    if pyinstaller_mode:
        os.environ["FONTCONFIG_PATH"] = os.path.join(install_directory, "etc\\fonts")#"C:\\msys64\\mingw64\\etc\\fonts"

phone = False
d = os.environ.get('XDG_CURRENT_DESKTOP')
if d in ["GNOME:Phosh"]:
    os.environ["SDL_VIDEODRIVER"] = "wayland"
    phone = True

if pyinstaller_mode: # and sys.platform == 'darwin':
    os.environ["PYSDL2_DLL_PATH"] = install_directory

fs_mode = False
if os.environ.get('GAMESCOPE_WAYLAND_DISPLAY') is not None:
    fs_mode = True
    print("Running in GAMESCOPE MODE")

allow_hidpi = True
if sys.platform == "win32" and sys.getwindowsversion().major < 10 or os.path.isfile(os.path.join(user_directory, "nohidpi")):
    allow_hidpi = False

from sdl2 import *
from sdl2.sdlimage import *

SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, b'1')
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, b"1")
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, b"0")
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best".encode())

draw_border = True
w = 1120
h = 600
if phone:
    w = 720
    h = 1800
window_default_size = [w, h]
window_size = [w, h]
logical_size = [w, h]
window_opacity = 1
scale = 1
if sys.platform == "darwin":
    scale = 2
if phone:
    scale = 1.3

maximized = False
old_window_position = None

window_p = os.path.join(user_directory, "window.p")
if os.path.isfile(window_p) and not fs_mode:
    try:
        state_file = open(window_p, "rb")
        save = pickle.load(state_file)
        state_file.close()

        draw_border = save[0]
        window_size = save[1]
        w, h = save[1]
        if 100 < w < 10000 and 100 < h < 5000:
            logical_size[0], logical_size[1] = w, h
        window_opacity = save[2]
        scale = save[3]
        maximized = save[4]
        old_window_position = save[5]
        del save

    except:
        print('Corrupted window state file?!')
        print('Please restart app')
        os.remove(window_p)
        exit(1)
else:
    print("No window state file")


if d == "GNOME": #and os.environ.get("XDG_SESSION_TYPE") and os.environ.get("XDG_SESSION_TYPE") == "wayland":
    try:
        import gi.repository
        gi.require_version('Gtk', '3.0')
        from gi.repository import Gtk

        gtk_settings = Gtk.Settings().get_default()
        xtheme = gtk_settings.get_property("gtk-cursor-theme-name")
        xsize = gtk_settings.get_property("gtk-cursor-theme-size")
        os.environ["XCURSOR_THEME"] = xtheme
        os.environ["XCURSOR_SIZE"] = str(xsize)
    except:
        pass

if os.environ.get("XDG_SESSION_TYPE") and os.environ.get("XDG_SESSION_TYPE") == "wayland":
    os.environ["SDL_VIDEODRIVER"] = "wayland"
if os.path.exists(os.path.join(user_directory, "x11")):
    os.environ["SDL_VIDEODRIVER"] = "x11"

SDL_Init(SDL_INIT_VIDEO)

err = SDL_GetError()
if err and "GLX" in err.decode():
    print(f"SDL init error: {err.decode()}")
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, b"Tauon Music Box failed to start :(",
                             b"Error: " + err + b".\n If you're using Flatpak, try run `$ flatpak update`", None)
    sys.exit()

window_title = t_title
window_title = window_title.encode('utf-8')

flags = SDL_WINDOW_RESIZABLE

if allow_hidpi:
    flags |= SDL_WINDOW_ALLOW_HIGHDPI

if draw_border and not fs_mode:
    flags |= SDL_WINDOW_BORDERLESS

if fs_mode:
    flags |= SDL_WINDOW_FULLSCREEN_DESKTOP

if old_window_position is None:
    o_x = SDL_WINDOWPOS_UNDEFINED
    o_y = SDL_WINDOWPOS_UNDEFINED
else:
    o_x = old_window_position[0]
    o_y = old_window_position[1]

if "--tray" in sys.argv:
    flags |= SDL_WINDOW_HIDDEN

error = False

t_window = SDL_CreateWindow(window_title,
                            o_x, o_y,
                            logical_size[0], logical_size[1],
                            flags) # | SDL_WINDOW_FULLSCREEN)



if maximized:
    SDL_MaximizeWindow(t_window)


renderer = SDL_CreateRenderer(t_window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)

if not renderer or not t_window:
    print("ERROR CREATING WINDOW!")

SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND)
SDL_SetWindowOpacity(t_window, window_opacity)

SDL_SetRenderDrawColor(renderer, 7, 7, 7, 255)
SDL_RenderClear(renderer)


i_x = pointer(c_int(0))
i_y = pointer(c_int(0))
SDL_GL_GetDrawableSize(t_window, i_x, i_y)
window_size[0] = i_x.contents.value
window_size[1] = i_y.contents.value

SDL_GetWindowSize(t_window, i_x, i_y)
logical_size[0] = i_x.contents.value
logical_size[1] = i_y.contents.value

img_path = os.path.join(asset_directory, "loading.png")
if scale != 1:
    img_path2 = os.path.join(user_directory, "scaled-icons", "loading.png")
    if os.path.isfile(img_path2):
        img_path = img_path2
    del img_path2

raw_image = IMG_Load(img_path.encode())
sdl_texture = SDL_CreateTextureFromSurface(renderer, raw_image)
w = raw_image.contents.w
h = raw_image.contents.h
rect = SDL_Rect(window_size[0] // 2 - w // 2, window_size[1] // 2 - h // 2, w, h)

SDL_RenderCopy(renderer, sdl_texture, None, rect)

SDL_RenderPresent(renderer)

SDL_FreeSurface(raw_image)
SDL_DestroyTexture(sdl_texture)

from t_modules import t_bootstrap
h = t_bootstrap.holder
h.w = t_window
h.r = renderer
h.wl = logical_size
h.wr = window_size
h.wdf = window_default_size
h.s = scale
h.m = maximized
h.e = transfer_args_and_exit
h.d = draw_border
h.o = window_opacity
h.ow = old_window_position
h.id = install_directory
h.py = pyinstaller_mode
h.p = phone
h.window_title = window_title
h.fs_mode = fs_mode
h.title = t_title
h.n_version = n_version
h.t_version = t_version
h.t_id = t_id
h.agent = t_agent
h.dev_mode = dev_mode
h.lock = fp

del raw_image
del sdl_texture
del w
del h
del rect
del flags
del img_path

if pyinstaller_mode or sys.platform == "darwin" or install_mode:
    from t_modules import t_main
else:
    # Using the above import method breaks previous pickles. Could be fixed
    # but yet to decide what best method is.
    big_boy_path = os.path.join(install_directory, 't_modules/t_main.py')
    f = open(big_boy_path, "rb")
    main = compile(f.read(), big_boy_path, 'exec')
    f.close()
    del big_boy_path
    del f
    exec(main)

