#!/usr/bin/env python3
import glob
import json
import os
import platform
import shutil
import stat
import subprocess
import sys
import tempfile
import unittest

WINDOWS = sys.platform.startswith('win')
MACOS = sys.platform == 'darwin'
MACOS_ARM64 = MACOS and platform.machine() == 'arm64'

emconfig = os.path.abspath('.emscripten')
assert os.path.exists(emconfig)

if WINDOWS:
    emsdk = 'emsdk.bat'
else:
    emsdk = './emsdk'

# Utilities


def listify(x):
    if type(x) in {list, tuple}:
        return x
    return [x]


def copy_emsdk_to(targetdir):
    for filename in os.listdir('.'):
        if not filename.startswith('.') and not os.path.isdir(filename):
            shutil.copy2(filename, os.path.join(targetdir, filename))


def check_call(cmd, **kwargs):
    if type(cmd) is not list:
        cmd = cmd.split()
    print(f'running: {cmd}')
    subprocess.run(cmd, check=True, text=True, **kwargs)


def checked_call_with_output(cmd, expected=None, unexpected=None, stderr=None, env=None):
    cmd = cmd.split(' ')
    print(f'running: {cmd}')
    try:
        stdout = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=stderr, check=True, text=True, env=env).stdout
    except subprocess.CalledProcessError as e:
        print(e.stderr)
        print(e.stdout)
        raise e

    if expected:
        for x in listify(expected):
            assert x in stdout, 'expected output missing: ' + stdout + '\n[[[' + x + ']]]'
    if unexpected:
        for x in listify(unexpected):
            assert x not in stdout, 'unexpected output present: ' + stdout + '\n[[[' + x + ']]]'


def failing_call_with_output(cmd, expected, env=None):
    proc = subprocess.run(cmd.split(' '), capture_output=True, text=True, env=env)
    stdout = proc.stdout
    stderr = proc.stderr
    if WINDOWS:
        print('warning: skipping part of failing_call_with_output() due to error codes not being propagated (see #592)')
    else:
        assert proc.returncode, 'call must have failed: ' + str([stdout, '\n========\n', stderr])
    assert expected in stdout or expected in stderr, 'call did not have the expected output: {}: {}'.format(expected, str([stdout, '\n========\n', stderr]))


def hack_emsdk(marker, replacement):
    with open('emsdk.py') as f:
        src = f.read()
    assert marker in src
    src = src.replace(marker, replacement)
    name = '__test_emsdk'
    with open(name, 'w') as f:
        f.write(src)
    return name


def get_longest_path_in_dir(dirname):
    longest = ''
    for root, _dirs, files in os.walk(dirname):
        for f in files:
            fullname = os.path.join(root, f)
            if len(fullname) > len(longest):
                longest = fullname
    return longest


def remove_file(filename):
    if os.path.exists(filename):
        os.remove(filename)


def remove_tree(path):
    if not os.path.exists(path):
        return
    if WINDOWS:
        path = '\\\\?\\' + path

    def remove_readonly(func, path2, _):
        os.chmod(path2, stat.S_IRWXU)
        func(path2)

    shutil.rmtree(path, onerror=remove_readonly)


# Set up

TAGS = json.loads(open('emscripten-releases-tags.json').read())

# Tests


def do_lib_building(emcc):
    cache_building_messages = ['generating system library: ']

    def do_build(args, is_expected=None):
        unexpected = None
        expected = None
        if is_expected is True:
            expected = cache_building_messages
        elif is_expected is False:
            unexpected = cache_building_messages
        checked_call_with_output(emcc + ' hello_world.c' + args,
                                 expected=expected,
                                 unexpected=unexpected,
                                 stderr=subprocess.STDOUT)

    # The emsdk ships all system libraries so we don't expect to see any
    # cache population unless we explicly --clear-cache.
    do_build('', is_expected=False)
    check_call(emcc + ' --clear-cache')
    do_build(' -O2', is_expected=True)
    # Do another build at -O0.  In nwers SDK versions this generates
    # different libs, but not in older ones so don't assert here.
    do_build('')
    # Now verify that libs are *not* build
    do_build(' -s WASM=0', is_expected=False)
    do_build(' -O2 -s WASM=0', is_expected=False)


def run_emsdk(cmd):
    if type(cmd) is not list:
        cmd = cmd.split()
    check_call([emsdk, *cmd])


def upstream_emcc(root='.'):
    emcc = os.path.join(root, 'upstream', 'emscripten', 'emcc')
    if WINDOWS:
        if os.path.exists(emcc + '.exe'):
            return emcc + '.exe'
        else:
            return emcc + '.bat'
    return emcc


class Emsdk(unittest.TestCase):
    def setUp(self):
        run_emsdk('install latest')
        run_emsdk('activate latest')
        with open('hello_world.c', 'w') as f:
            f.write('''\
      #include <stdio.h>

      int main() {
         printf("Hello, world!\\n");
         return 0;
      }
      ''')
        self.addCleanup(remove_file, 'hello_world.c')

    def tearDown(self):
        for f in glob.glob('a.out*'):
            os.remove(f)

    def test_extrememly_long_filenames(self):
        # We have special support for filenames longer than 256 on windows. This
        # test installs emsdk in path that exceeds this limit in order to test
        # this handling.
        longpath = os.path.abspath('very_long_filename_indeed')

        additional = 140 - len(longpath)
        longpath += 'x' * additional

        remove_tree(longpath)
        self.addCleanup(remove_tree, longpath)

        os.makedirs(longpath)
        copy_emsdk_to(longpath)

        emsdk = os.path.join(longpath, 'emsdk')
        if WINDOWS:
            emsdk += '.bat'
        self.assertTrue(os.path.exists(emsdk))

        check_call([emsdk, 'install', 'latest'])
        check_call([emsdk, 'activate', 'latest'])

        # Check that emcc exists in the expected location
        emcc = upstream_emcc(longpath)
        print(emcc)
        self.assertTrue(os.path.exists(emcc))

        # Find the longest installed path and assert this is longer than 256
        longest_path = get_longest_path_in_dir(longpath)
        print(f'longest ({len(longest_path)}: {longest_path})')
        self.assertGreater(len(longest_path), 256)

        # Finally make sure we can actaully compile something
        check_call([emcc, 'hello_world.c'])

    def test_unknown_arch(self):
        env = os.environ.copy()
        env['EMSDK_ARCH'] = 'mips'
        failing_call_with_output(emsdk + ' install latest',
                                 expected='unknown machine architecture: mips',
                                 env=env)

    def test_wrong_bitness(self):
        env = os.environ.copy()
        env['EMSDK_ARCH'] = 'x86'
        failing_call_with_output(emsdk + ' install sdk-latest-64bit',
                                 expected='is only provided for 64-bit OSe',
                                 env=env)

    def test_already_installed(self):
        # Test we don't re-download unnecessarily
        checked_call_with_output(emsdk + ' install latest', expected='already installed', unexpected='Downloading:')

    def test_list(self):
        # Test we report installed tools properly. The latest version should be
        # installed, but not some random old one.
        checked_call_with_output(emsdk + ' list', expected=TAGS['aliases']['latest'] + '    INSTALLED', unexpected='1.39.15    INSTALLED:')

    def test_config_contents(self):
        print('test .emscripten contents')
        run_emsdk('install 6.0.3')
        run_emsdk('activate 6.0.3')
        with open(emconfig) as f:
            config = f.read()
        self.assertIn('upstream', config)

        # Older version of emscripten (prior to 6.0.3) don't support $CFGDIR
        self.assertIn('import os', config)
        self.assertIn('emsdk_path + ', config)
        self.assertNotIn('$CFGDIR', config)

        # For newer versions we use $CFGDIR
        version_file = os.path.join('upstream', 'emscripten', 'emscripten-version.txt')
        with open(version_file) as f:
            old_ver = f.read()
        try:
            # Hack the version file to contain 6.0.4
            with open(version_file, 'w') as f:
                f.write('6.0.4\n')
            # Re-activate 6.0.3 but with the hacked version file which makes it
            # appear to contain 6.0.4.
            run_emsdk('activate 6.0.3')
            with open(emconfig) as f:
                config = f.read()
            self.assertNotIn('import os', config)
            self.assertNotIn('emsdk_path', config)
            self.assertIn('$CFGDIR', config)
        finally:
            with open(version_file, 'w') as f:
                f.write(old_ver)
            run_emsdk('activate 6.0.3')

    def test_activated_migration(self):
        print('test migration from .emscripten to activated.json')
        activated_json = os.path.abspath('activated.json')
        if os.path.exists(activated_json):
            os.remove(activated_json)

        run_emsdk('install 6.0.3')
        run_emsdk('activate 6.0.3')

        # Remove activated.json to force migration from .emscripten
        self.assertTrue(os.path.exists(activated_json))
        os.remove(activated_json)

        # Re-running emsdk list should populate activated.json from .emscripten
        checked_call_with_output(emsdk + ' list', expected='INSTALLED')
        self.assertTrue(os.path.exists(activated_json))
        with open(activated_json) as f:
            data = json.load(f)
        self.assertIn('active_tools', data)
        for t in data['active_tools']:
            print('active:', t)
        self.assertIn('node-24.19.0-64bit', data['active_tools'])

    def test_lib_building(self):
        print('building proper system libraries')
        do_lib_building(upstream_emcc())

    def test_redownload(self):
        print('go back to using upstream')
        run_emsdk('activate latest')

        # Test the normal tools like node don't re-download on re-install
        print('another install must re-download')
        checked_call_with_output(emsdk + ' uninstall node-24.19.0-64bit')
        checked_call_with_output(emsdk + ' install node-24.19.0-64bit', expected='Downloading:', unexpected='already installed')
        checked_call_with_output(emsdk + ' install node-24.19.0-64bit', unexpected='Downloading:', expected='already installed')

    def test_tot_upstream(self):
        print('test tot-upstream')
        run_emsdk('install tot-upstream')
        with open(emconfig) as f:
            config = f.read()
        run_emsdk('activate tot-upstream')
        self.addCleanup(remove_file, emconfig + '.old')
        with open(emconfig + '.old') as f:
            old_config = f.read()
        self.assertEqual(config, old_config)
        # TODO; test on latest as well
        check_call(upstream_emcc() + ' hello_world.c')

    def test_closure(self):
        # Specifically test with `--closure` so we know that node_modules is working
        check_call(upstream_emcc() + ' hello_world.c --closure=1')

    def test_specific_version(self):
        if MACOS_ARM64:
            self.skipTest('Old sdk versions do not have ARM64 binaries')
        print('test specific release (new, short name)')
        run_emsdk('install 1.38.33')
        print('another install, but no need for re-download')
        checked_call_with_output(emsdk + ' install 1.38.33', expected='Skipped', unexpected='Downloading:')
        run_emsdk('activate 1.38.33')

    def test_specific_version_full(self):
        if MACOS_ARM64:
            self.skipTest('Old sdk versions do not have ARM64 binaries')
        print('test specific release (new, full name)')
        run_emsdk('install sdk-1.38.33-64bit')
        run_emsdk('activate sdk-1.38.33-64bit')
        print('test specific release (new, tag name)')
        run_emsdk('install sdk-tag-1.38.33-64bit')
        run_emsdk('activate sdk-tag-1.38.33-64bit')

    def test_binaryen_from_source(self):
        if WINDOWS:
            # It takes over 30 mins to build binaryen using Visual Studio in CI
            self.skipTest('test is too slow under windows')
        run_emsdk(['install', '--build=Release', 'binaryen-main-64bit'])

    def test_no_32bit(self):
        print('test 32-bit error')
        emsdk_hacked = hack_emsdk('not is_os_64bit()', 'True')
        self.addCleanup(remove_file, emsdk_hacked)
        failing_call_with_output(f'{sys.executable} {emsdk_hacked} install latest',
                                 'this tool is only provided for 64-bit OSes')

    def test_update_no_git(self):
        print('test non-git update')

        temp_dir = tempfile.mkdtemp()
        self.addCleanup(remove_tree, temp_dir)
        copy_emsdk_to(temp_dir)

        olddir = os.getcwd()
        try:
            os.chdir(temp_dir)
            run_emsdk('update')

            print('second time')
            run_emsdk('update')
        finally:
            os.chdir(olddir)

    def test_install_arbitrary(self):
        # Test that its possible to install arbrary emscripten-releases SDKs
        run_emsdk('install 1b7f7bc6002a3ca73647f41fc10e1fac7f06f804')

        # Check that its not re-downloaded
        checked_call_with_output(emsdk + ' install 1b7f7bc6002a3ca73647f41fc10e1fac7f06f804', expected='Skipped', unexpected='Downloading:')

    def test_install_tool(self):
        # Test that its possible to install emscripten as tool instead of SDK
        checked_call_with_output(emsdk + ' install releases-77b065ace39e6ab21446e13f92897f956c80476a', unexpected='Installing SDK')

    def test_activate_missing(self):
        run_emsdk('install latest')
        expected = "error: tool is not installed and therefore cannot be activated: 'releases-13e29bd55185e3c12802bc090b4507901856b2ba-64bit'"
        failing_call_with_output(emsdk + ' activate 2.0.1', expected=expected)

    def test_keep_downloads(self):
        env = os.environ.copy()
        env['EMSDK_KEEP_DOWNLOADS'] = '1'
        # With EMSDK_KEEP_DOWNLOADS the downloading should happen on the first
        # install of 2.0.28, and again when we install 2.0.29, but not on the
        # second install of 2.0.28 because the zip should already be local.
        shutil.rmtree('downloads')
        checked_call_with_output(emsdk + ' install 3.1.54', expected='Downloading:', env=env)
        checked_call_with_output(emsdk + ' install 3.1.55', expected='Downloading:', env=env)
        checked_call_with_output(emsdk + ' install 3.1.54', expected='already downloaded, skipping', unexpected='Downloading:', env=env)

    def test_unicode_path(self):
        temp_dir = tempfile.mkdtemp(prefix='test_työpöytä_')
        self.addCleanup(remove_tree, temp_dir)
        copy_emsdk_to(temp_dir)

        olddir = os.getcwd()
        try:
            os.chdir(temp_dir)
            run_emsdk('list')
            run_emsdk('construct_env')
        finally:
            os.chdir(olddir)


if __name__ == '__main__':
    unittest.main(verbosity=2)
