# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Use with an IDE to copy a link to the current file/line to your clipboard.

Public and private repos are supported. The internal/public arguments are only
used if the repo is public, private repos always link to the internal code
search.

By default always generates a link to the public code search, but can also
generate links to the internal code search.

Currently only works locally and if using X11.

To allow use over SSH, enable X11 forwarding.
Client side: -X, or add "X11Forwarding yes" to your ~/.ssh/config.
Server side: "X11Forwarding yes" must be in /etc/ssh/sshd_config.

IDE integration instructions. Please add your IDE if it's not listed, or update
the instructions if they're vague or out of date!

For Intellij:
Create a new External Tool (Settings > Tools > External Tools).
Tool Settings:
    Program: ~/chromiumos/chromite/contrib/generate_cs_path
    Arguments: $FilePath$ -l $LineNumber$

For VSCode:
Create a custom task (code.visualstudio.com/docs/editor/tasks#_custom-tasks)
with the command:
    ~/chromiumos/chromite/contrib/generate_cs_path ${file} -l ${lineNumber}
"""

import os
from pathlib import Path
import sys

from chromite.lib import commandline
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import git


class CodeSearch:
    """format returns a url to the code specified"""

    @classmethod
    def format(cls, attrs, opts, checkout_path, relative_path) -> None:
        raise NotImplementedError()


class Gitiles(CodeSearch):
    """format returns a url to the code specified"""

    @classmethod
    def format(cls, attrs, opts, checkout_path, relative_path):
        line = f"#{opts.line}" if opts.line else ""
        return f'{attrs["push_url"]}/+/{attrs["sha"]}/{relative_path}{line}'


class PublicCS(CodeSearch):
    """format returns a url to the code specified"""

    @classmethod
    def format(cls, attrs, opts, checkout_path, relative_path):
        line = f";l={opts.line}" if opts.line else ""
        sha = attrs["sha"] if opts.upstream_sha else "HEAD"
        # HEAD is the ref for the codesearch repo, not the project itself.
        return (
            "https://source.chromium.org/chromiumos/chromiumos/codesearch/+/"
            + f"{sha}:{checkout_path}/{relative_path}{line}"
        )


class InternalCS(CodeSearch):
    """format returns a url to the code specified"""

    @classmethod
    def format(cls, attrs, opts, checkout_path, relative_path):
        line = f";l={opts.line}" if opts.line else ""
        sha = f';rcl={attrs["sha"]}' if opts.upstream_sha else ""
        return (
            "http://cs/h/chrome-internal/chromeos/superproject/+/main:"
            + f"{checkout_path}/{relative_path}{line}{sha}"
        )


def GetParser():
    """Build the argument parser."""
    parser = commandline.ArgumentParser(description=__doc__)

    # Public/internal code search selection arguments.
    type_group = parser.add_mutually_exclusive_group()
    type_group.add_argument(
        "-p",
        "--public",
        dest="public_link",
        action="store_true",
        default=True,
        help="Generate a link to the public code search.",
    )
    type_group.add_argument(
        "-i",
        "--internal",
        dest="public_link",
        action="store_false",
        help="Generate a link to the internal code search.",
    )
    type_group.add_argument(
        "-g",
        "--gitiles",
        action="store_true",
        default=False,
        help="Generate a gitiles link rather than a code search link.",
    )

    parser.add_argument("-l", "--line", type=int, help="Line number.")
    parser.add_argument(
        "--upstream-sha", action="store_true", help="Link to the upstream sha."
    )

    action_group = parser.add_mutually_exclusive_group()
    action_group.add_argument(
        "-o",
        "--open",
        action="store_true",
        default=False,
        help="Open the link in a browser rather than copying it to the "
        "clipboard.",
    )
    action_group.add_argument(
        "-s",
        "--show",
        action="store_true",
        default=False,
        help="Output the link to stdout rather than copying it to the "
        "clipboard.",
    )

    parser.add_argument("path", type="str_path", help="Path to a file.")

    return parser


def ParseArguments(argv):
    """Parse and validate arguments."""
    parser = GetParser()
    opts = parser.parse_args(argv)

    opts.path = Path(opts.path).relative_to(constants.SOURCE_ROOT)

    opts.Freeze()
    return opts


def GenerateLink(attrs, opts, checkout_path, relative_path):
    """Generate link to CS based on on parsed arguments and checkout."""
    if opts.gitiles:
        base = Gitiles
    elif attrs.get("remote_alias") == "cros-internal":
        # Private repos not on public CS, so force internal private.
        base = InternalCS
    elif opts.public_link:
        base = PublicCS
    else:
        base = InternalCS

    return base.format(attrs, opts, checkout_path, relative_path)


def main(argv) -> None:
    opts = ParseArguments(argv)

    checkout = git.ManifestCheckout.Cached(opts.path)

    # Find the project.
    checkout_path = None
    attrs = {}
    for checkout_path, attrs in checkout.checkouts_by_path.items():
        try:
            relative_path = opts.path.relative_to(checkout_path)
            break
        except ValueError:
            continue
    else:
        cros_build_lib.Die("No project found for %s.", opts.path)

    if opts.upstream_sha:
        attrs["sha"] = git.RunGit(
            attrs["local_path"], ["rev-parse", attrs["tracking_branch"]]
        ).stdout.strip()
    else:
        attrs["sha"] = git.RunGit(
            attrs["local_path"], ["rev-parse", "HEAD"]
        ).stdout.strip()

    final_link = GenerateLink(attrs, opts, checkout_path, relative_path)

    is_mac_os = sys.platform.startswith("darwin")

    if opts.open:
        cmd = ["open" if is_mac_os else "xdg-open", final_link]
        os.execvp(cmd[0], cmd)
    elif opts.show:
        print(final_link)
    else:
        cmd = ["pbcopy"] if is_mac_os else ["xsel", "--clipboard", "--input"]
        cros_build_lib.run(cmd, input=final_link)
