# This renders Wavetapper in the terminal, and is dependent on termtapper.json

import os
import sys
import ctypes
import platform
import json
from urllib.request import urlopen
from time import sleep
from datetime import datetime
import subprocess


def print_frame(frame, back, fore, n, m):
    SET_CURSOR(n, m)

    for y in range(0, 11, 2):

        SAVE_CURSOR()

        for x in range(11):
            top = fore if frame[y-1][x] == '#' else back
            bot = fore if frame[y][x] == '#' else back
            SET_COLOR(bot, top if y > 0 else 0)
            sys.stdout.write('▄')

        LOAD_CURSOR()
        CURSOR_DOWN()


def play_audio():
    try:
        proc = subprocess.Popen(['mpv',
                                 'https://soundcloud.com/frums/wavetapper'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.DEVNULL)
        print('Loading audio from SoundCloud (using mpv)...')
        proc.stdout.read(1)
        return 69
    except FileNotFoundError:
        pass

    try:
        proc = subprocess.Popen(['vlc', '--intf', 'dummy', '--verbose=2',
                                 'https://soundcloud.com/frums/wavetapper'],
                                stdout=subprocess.DEVNULL,
                                stderr=subprocess.PIPE)
        print('Loading audio from SoundCloud (using vlc)...')
        while line := str(proc.stderr.readline()):
            if 'started' in line:
                return 69
    except FileNotFoundError:
        pass

    if platform.system().lower() == "windows":
        try:
            SET_COLOR(196, 0)
            print("\n")
            print("WARNING: I couln't figure out how to stop sound on Windows.")
            print("Please search for 'vlc' in the command line when you need to kill the music.")
            RESET_COLOR()
            print()
            path = os.environ.get('ProgramFiles') + r'\VideoLAN\VLC\vlc.exe'
            proc = subprocess.Popen([path, '--intf', 'dummy', '--verbose=2',
                                    'https://soundcloud.com/frums/wavetapper'],
                                    stdout=subprocess.DEVNULL,
                                    stderr=subprocess.PIPE)
            print('Loading audio from SoundCloud (using vlc)...')
            sleep(7)
            return 29
        except FileNotFoundError:
            pass

    SET_COLOR(196, 0)
    print("\n")
    print("WARNING: Cannot play sound.")
    print("Either vlc or mpv must be installed")
    print("and available from the terminal.")
    print("Termtapper will play silently in 7 seconds...")
    RESET_COLOR()
    print()
    sleep(7)
    return 0


def show_video():

    queue = []

    for j, row in enumerate(data['boxes']):
        for i, box in enumerate(row):
            back = data['colors'][j][i][0]
            fore = data['colors'][j][i][1]
            for side in box:
                for [time, frame] in box[side]:
                    queue.append((time, frame, back, fore, 1+j*6, 2+i*12))

    queue.sort()

    offset = play_audio()
    starttime = datetime.now()

    HIDE_CURSOR()
    USE_ALTERNATE_SCREEN_BUFFER()

    for (time, frame, back, fore, y, x) in queue:
        tosleep = (time-offset)/30 - (datetime.now() - starttime).total_seconds()
        if tosleep > 0:
            sys.stdout.flush()
            sleep(tosleep)
        print_frame(data['frames'][frame], back, fore, y, x)


# LOAD AND CUSTOMIZE FRAMES

# with open('termtapper.json', 'r') as file:
#     data = json.load(file)

with urlopen("http://termtapper.top/termtapper.json") as response:
    data = json.loads(response.read().decode('utf-8'))

CUSTOM_ENDING = [
    [2, 187, 188, 189],
    [190, 191, 192, 6],
    [193, 194, 195, 196],
    [122, 123, 135, 146]
]

for j, row in enumerate(data['boxes']):
    for i, box in enumerate(row):
        box['left'][-1][1] = CUSTOM_ENDING[j][i]
        box['right'][-1][1] = CUSTOM_ENDING[j][i]


def ANSI(*xs, sep='', end=''):
    code = '\033[' + sep.join(str(x) for x in xs) + end
    return lambda: sys.stdout.write(code)


USE_ALTERNATE_SCREEN_BUFFER = ANSI('?', 1049, end='h')
USE_NORMAL_SCREEN_BUFFER = ANSI('?', 1049, end='l')
SHOW_CURSOR = ANSI('?', 25, end='h')
HIDE_CURSOR = ANSI('?', 25, end='l')
SAVE_CURSOR = ANSI('s')
LOAD_CURSOR = ANSI('u')
RESET_COLOR = ANSI(end='m')
def SET_CURSOR(n, m): ANSI(n, m, sep=';', end='H')()
def CURSOR_DOWN(n=1): ANSI(n, end='B')()
def SET_COLOR(fore, back): ANSI(38, 5, fore, 48, 5, back, sep=';', end='m')()


# Enable ansi colors on Windows
if platform.system().lower() == "windows":
    kernel32 = ctypes.windll.kernel32
    kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)


try:
    show_video()
    sleep(5)
    SHOW_CURSOR()
    RESET_COLOR()
    USE_NORMAL_SCREEN_BUFFER()
    print("Thanks for watching until the end :D")
except KeyboardInterrupt:
    SHOW_CURSOR()
    RESET_COLOR()
    USE_NORMAL_SCREEN_BUFFER()
    print("Thanks for watching :)")


print("Song:       Wavetapper - Frums")
print('YouTube:    https://youtu.be/-lRPEny5jug')
print('SoundCloud: https://soundcloud.com/frums/wavetapper')
