#!/usr/bin/env python
import subprocess
import logging
import sys,os

# Verify that arc is installed.
class TwitchArc(object):

    # Our logging object.
    log = logging.Logger('TwitchArc')

    # Path where we expect arc to be installed.
    arc_path = "/usr/local/bin/arc"

    # Path where we expect arc to be installed.
    git_path = "/usr/local/bin/git"

    # Path where we expect arc to be installed.
    hub_path = "/usr/local/bin/hub"

    # Our working directory.
    working_dir = os.getcwd()

    @classmethod
    def is_setup(cls):
        """
        Checks to make sure that our system is configured with the proper command-line tools that we need.

        :return: bool
        """
        its_all_good = True
        arc_installed = os.path.exists(cls.arc_path)
        if not arc_installed:
            its_all_good = False
            cls.log.warning("arc is not installed!")
        git_installed = os.path.exists(cls.git_path)
        if not git_installed:
            its_all_good = False
            cls.log.warning("git is not installed!")
        hub_installed = os.path.exists(cls.hub_path)
        if not hub_installed:
            its_all_good = False
            cls.log.warning("hub is not installed!")
        return its_all_good

    @classmethod
    def setup(cls):
        """
        Checks to see if our system is setup, if not then attempts to install the necessary dependencies via Homebrew.
        """
        if not cls.is_setup():
            # Make sure that arc is installed.
            if not os.path.exists(cls.arc_path):
                raise Exception("Arc is not installed!")
            TwitchArc.log.info("Arc is installed, muy bien.")

            # Check to see if brew is installed.
            if not subprocess.check_output(['which','brew']):
                raise Exception("Homebrew is not installed!")
            TwitchArc.log.info("Homebrew is installed, tres bon.")

            # Make sure git is installed.
            if not subprocess.check_output(['brew','ls','--versions','git']):
                TwitchArc.log.info("Installing git via Homebrew")
                os.system('brew install git')

            # Make sure hub is installed.
            if not subprocess.check_output(['brew','ls','--versions','hub']):
                TwitchArc.log.info("Installing hub via Homebrew and configuring environment for Twitch")
                os.system('brew install hub')
                os.system('git config --global --add hub.host git-aws.internal.justin.tv')
                os.system('echo \'export GITHUB_HOST=git-aws.internal.justin.tv\' > ~/.bash_profile')

        # If sublime is installed on the system, then set it as the text editor for arc.
        subl_path = subprocess.check_output(['which','subl']).rstrip()
        if subl_path:
            TwitchArc.log.info("Sublime detected, setting it as the Arc Editor")
            os.system('arc set-config editor \'%s -w -n\''%subl_path)

    @classmethod
    def run(cls,target_branch):
        """
        Runs 'arc diff' against a defined branch.  If a diff is ceated by arc, then we'll also create a GitHub pull-request
        for the project and link it to the diff in phabriator created by the arc command.

        :param target_branch: Branch tha we want to merge our changes into.
        """

        # Make sure that we got all of the commands that we need.
        if not cls.is_setup():
            raise Exception("Missing required components, run '--setup' to resolve.")

        # Make sure the working directory is a git project.
        working_dir = os.getcwd()
        if not working_dir.endswith("/"):
            working_dir += "/"
        git_dir = working_dir + ".git" + "/"
        if not os.path.isdir(git_dir):
            raise Exception("Project isn't in git (missing '.git' directory)")

        # Setup our tmp file that stores the output from our arc command.
        arc_output_path = "/tmp/twarc.log"
        if os.path.exists(arc_output_path):
            os.remove(arc_output_path)

        # Now run the arc command and direct it's output to the tmp file.
        os.system("%s diff %s 2>&1 | tee %s"%(cls.arc_path,target_branch,arc_output_path))

        # Now open up the output from our arc command and try to pull out the URL.
        arc_url = ""
        with open(arc_output_path) as f:
            for line in f.readlines():
                uri_str = "Revision URI:"
                line = line.lstrip()
                if line.startswith(uri_str):
                    line = line[line.find(uri_str) + len(uri_str):]
                    arc_url = line.strip()

        # If we were able to get a URL and we have our create message from when we made the arc, then go ahead and make
        # our git_msg so we can create a pull request in git.
        arc_msg_path = git_dir + "arc/create-message"
        git_msg_path = "/tmp/twarc_git.log"
        if arc_url and os.path.exists(arc_msg_path):
            # Now grab the file that was generated by the arc command.
            summary_str = ""
            commit_str = ""
            with open(arc_msg_path) as f:
                triggered_msg = False
                for line in f.readlines():
                    if triggered_msg:
                        if line.lstrip().startswith("Test Plan:"):
                            break
                        summary_str += line
                    elif line.lstrip().startswith("Summary:"):
                        commit_str = commit_str.rstrip()
                        triggered_msg = True
                        line = line[line.find("Summary:") + len("Summary:"):]
                        line = line.lstrip()
                        summary_str += line
                    elif not triggered_msg:
                        commit_str += line

            # Now use the strings we got to create our git message.
            git_msg_str = ""
            git_msg_str += commit_str + "\n\n"
            git_msg_str += arc_url + "\n"
            git_msg_str += "----------\n"
            git_msg_str += summary_str

            # Now write that string to a file.
            with open(git_msg_path, 'w') as f:
                f.write(git_msg_str)

            # Now alas, let's create a git pull-request, using the message we just generated.
            os.system("echo $PATH ; hub pull-request -F %s" % git_msg_path)

if __name__ == "__main__":

    import argparse

    # Check to make sure that the system python is 2.7 (needed for 'subprocess.check_output'), if not then we bail.
    if sys.version_info < (2,7):
        raise Exception("Must run with python 2.7 or greater.  Install python with 'brew install python' to resolve this error.")

    parser = argparse.ArgumentParser(description='Wrapper to arc cmd, that will create a GitHub pull-request, when an Arc diff is created.')
    parser.add_argument('target_branch',type=str,nargs='?',default='origin/master',help="Target branch that you want to merge this branch into.  By default is 'origin/master'")
    parser.add_argument('--setup',action='store_true',default=False,help="If set, will run setup to ensure dependencies for this script are installed")

    args = parser.parse_args()

    if args.setup:
        TwitchArc.setup()

    TwitchArc.run(args.target_branch)
