from __future__ import print_function
# ------------------------------------------------------------------------------------------------
# Copyright (c) 2016 Microsoft Corporation
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
# associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ------------------------------------------------------------------------------------------------

# Used for integration tests.

from builtins import str
from builtins import range
import io
import os
import platform
import socket
import subprocess
import sys
import time


def _port_has_listener(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    result = sock.connect_ex(('127.0.0.1', port))
    sock.close()
    return result == 0


def launch_minecraft_in_background(minecraft_path, ports=None, timeout=360, replaceable=False, score=False, max_mem=None):
    # Note: max_mem is a string in the same format as the "-Xmx" option to java, e.g. "4G".
    if ports is None:
        ports = []
    if len(ports) == 0:
        ports = [10000]  # Default
    processes = []
    for port in ports:
        if _port_has_listener(port):
            print('Something is listening on port', port, '- will assume Minecraft is running.')
            continue
        replaceable_arg = " -replaceable " if replaceable else ""
        scorepolicy_arg = " -scorepolicy " if score else ""
        scorepolicy_value = " 2 " if score else ""
        maxmem_arg = " -maxMem " if max_mem is not None else ""
        maxmem_value = " " + max_mem + " " if max_mem else ""
        print('Nothing is listening on port', port, '- will attempt to launch Minecraft from a new terminal.')
        if os.name == 'nt':
            args = [minecraft_path + '/launchClient.bat', '-port', str(port), replaceable_arg.strip(),
                    scorepolicy_arg.strip(), scorepolicy_value.strip(), maxmem_arg.strip(), maxmem_value.strip()]
            p = subprocess.Popen([arg for arg in args if arg != ""],
                                 creationflags=subprocess.CREATE_NEW_CONSOLE, close_fds=True)
        elif sys.platform == 'darwin':
            # Can't pass parameters to launchClient via Terminal.app, so create a small launch
            # script instead.
            # (Launching a process to run the terminal app to run a small launch script to run
            # the launchClient script to run Minecraft... is it possible that this is not the most
            # straightforward way to go about things?)
            launcher_file = "/tmp/launcher_" + str(os.getpid()) + ".sh"
            tmp_file = open(launcher_file, "w")
            tmp_file.write(minecraft_path + '/launchClient.sh -port ' + str(port) +
                           replaceable_arg + scorepolicy_arg + scorepolicy_value + maxmem_arg + maxmem_value)
            tmp_file.close()
            os.chmod(launcher_file, 0o700)
            p = subprocess.Popen(['open', '-a', 'Terminal.app', launcher_file])
        else:
            p = subprocess.Popen(minecraft_path + "/launchClient.sh -port " + str(port) +
                                 replaceable_arg + scorepolicy_arg + scorepolicy_value + maxmem_arg + maxmem_value,
                                 close_fds=True, shell=True,
                                 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        processes.append(p)
        print('Giving Minecraft some time to launch... ')
        launched = False
        for _ in range(timeout // 3):
            print('.', end=' ')
            time.sleep(3)
            if _port_has_listener(port):
                print('ok')
                launched = True
                break
        if not launched:
            print('Minecraft not yet launched. Giving up.')
            exit(1)
    return processes


if __name__ == "__main__":
    minecraft_launch_path = os.path.dirname(os.path.abspath(__file__))
    launch_ports = [int(port_arg) for port_arg in sys.argv[1:] if port_arg != "--replaceable" and port_arg != "--score"]
    launch_minecraft_in_background(minecraft_launch_path, launch_ports, 300,
                                   replaceable="--replaceable" in sys.argv,
                                   score="--score" in sys.argv)
