import os
import itertools
import subprocess

from .environ import get_environment_from_batch_command


class VisualStudio(str):
    @classmethod
    def find(cls, versions=['9.0', '10.0']):
        r"""
        Find the location of the locally-installed
        Visual Studio instance. Uses the heuristic of searching the
        default paths for the supplied versions.

        Versions should be a string or list of strings
        indicating the version
        as found in the file path.

        >>> VisualStudio.find('9.0') #doctest:+SKIP
        'C:\\Program Files\\Microsoft Visual Studio 9.0'
        """
        if isinstance(versions, str):
            versions = [versions]
        keys = ['PROGRAMFILES', 'PROGRAMFILES(X86)']
        search_path = [os.environ[key] for key in keys if key in os.environ]
        path_versions = itertools.product(search_path, versions)
        vs_candidate_dirs = [
            os.path.join(base, 'Microsoft Visual Studio ' + version)
            for base, version in path_versions
        ]

        def has_VC_child(dir):
            return os.path.isdir(os.path.join('VC'))

        tests = os.path.isdir, has_VC_child

        def test_adequacy(candidate):
            return all(t(candidate) for t in tests)

        path = next(iter(filter(test_adequacy, vs_candidate_dirs)))
        return cls(path)

    def get_vcvars_env(self, *params):
        """
        Get the environment variables generated by running
        vcvarsall.bat in Visual Studio 9.
        Additional parameters will be passed to the script.
        """
        vcvarsall = os.path.join(self, 'VC', 'vcvarsall.bat')
        if not os.path.isfile(vcvarsall):
            msg = "Couldn't find vcvarsall"
            raise RuntimeError(msg)
        return get_environment_from_batch_command([vcvarsall] + list(params))

    def upgrade(self, file):
        """
        Upgrade project or solution file to the current version
        """
        devenv = os.path.join(self, 'Common7', 'IDE', 'devenv.com')
        subprocess.check_call([devenv, file, '/upgrade'])


def upgrade_file():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', help="Solution or Project file")
    args = parser.parse_args()
    vs = VisualStudio.find()
    return vs.upgrade(args.filename)
