#!/usr/bin/env python3
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Prints the lowest locally available SDK version greater than or equal to a
given minimum sdk version to standard output.

Usage:
  python3 find_sdk.py 10.6  # Ignores SDKs < 10.6
"""

import os
import re
import subprocess
import sys

from optparse import OptionParser


# sdk/build/xcode_links
ROOT_SRC_DIR = os.path.join(
    os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))


def CreateSymlinkForSDKAt(src, dst):
    """
    Create symlink to Xcode directory at target location, which can be absolute or
    relative to `ROOT_SRC_DIR`.
    """

    # If `dst` is relative, it is assumed to be relative to src root.
    if not os.path.isabs(dst):
        dst = os.path.join(ROOT_SRC_DIR, dst)

    if not os.path.isdir(dst):
        os.makedirs(dst)

    dst = os.path.join(dst, os.path.basename(src))

    # Update the symlink if exists.
    if os.path.islink(dst):
        current_src = os.readlink(dst)
        if current_src == src:
            return dst

        os.unlink(dst)
        sys.stderr.write('existing symlink %s points %s; want %s. Removed.' %
                         (dst, current_src, src))

    os.symlink(src, dst)
    return dst


def parse_version(version_str):
    """'10.6' => [10, 6]"""
    return list(map(int, re.findall(r'(\d+)', version_str)))


def main():
    parser = OptionParser()
    parser.add_option(
        "--verify",
        action="store_true",
        dest="verify",
        default=False,
        help="return the sdk argument and warn if it doesn't exist")
    parser.add_option(
        "--sdk_path",
        action="store",
        type="string",
        dest="sdk_path",
        default="",
        help="user-specified SDK path; bypasses verification")
    parser.add_option(
        "--print_sdk_path",
        action="store_true",
        dest="print_sdk_path",
        default=False,
        help="Additionaly print the path the SDK (appears first).")
    parser.add_option(
        "--create_symlink_at",
        action="store",
        dest="create_symlink_at",
        help=
        "Create symlink to SDK at given location and return symlink path as SDK "
        "info instead of the original location.")
    (options, args) = parser.parse_args()
    min_sdk_version = args[0]

    job = subprocess.Popen(['xcode-select', '-print-path'],
                           stdout=subprocess.PIPE,
                           stderr=subprocess.STDOUT,
                           universal_newlines=True)
    out, err = job.communicate()
    if job.returncode != 0:
        print(out, file=sys.stderr)
        print(err, file=sys.stderr)
        raise Exception((
            'Error %d running xcode-select, you might have to run '
            '|sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer| '
            'if you are using Xcode 4.') % job.returncode)
    # The Developer folder moved in Xcode 4.3.
    xcode43_sdk_path = os.path.join(out.rstrip(),
                                    'Platforms/MacOSX.platform/Developer/SDKs')
    if os.path.isdir(xcode43_sdk_path):
        sdk_dir = xcode43_sdk_path
    else:
        sdk_dir = os.path.join(out.rstrip(), 'SDKs')
    sdks = [
        re.findall('^MacOSX(1[01]\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)
    ]
    sdks = [s[0] for s in sdks if s]  # [['10.5'], ['10.6']] => ['10.5', '10.6']
    sdks = [
        s for s in sdks  # ['10.5', '10.6'] => ['10.6']
        if parse_version(s) >= parse_version(min_sdk_version)
    ]
    if not sdks:
        raise Exception('No %s+ SDK found' % min_sdk_version)
    best_sdk = sorted(sdks, key=parse_version)[0]

    if options.verify and best_sdk != min_sdk_version and not options.sdk_path:
        print('''
                                           vvvvvvv

This build requires the %s SDK, but it was not found on your system.

Either install it, or explicitly set mac_sdk in your GYP_DEFINES.

                                           ^^^^^^^'
''' % min_sdk_version,
              file=sys.stderr)
        return min_sdk_version

    if options.print_sdk_path:
        sdk_path = subprocess.check_output(
            ['xcodebuild', '-version', '-sdk', 'macosx' + best_sdk, 'Path'],
            universal_newlines=True).strip()
        if options.create_symlink_at:
            print(CreateSymlinkForSDKAt(sdk_path, options.create_symlink_at))
        else:
            print(sdk_path)

    return best_sdk


if __name__ == '__main__':
    if sys.platform != 'darwin':
        raise Exception("This script only runs on Mac")
    print(main())
