import hashlib
import logging
import sys
from optparse import Values
from typing import List

from pip._internal.cli.base_command import Command
from pip._internal.cli.status_codes import ERROR, SUCCESS
from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES
from pip._internal.utils.misc import read_chunks, write_output

logger = logging.getLogger(__name__)


class HashCommand(Command):
    """
    Compute a hash of a local package archive.

    These can be used with --hash in a requirements file to do repeatable
    installs.
    """

    usage = "%prog [options] <file> ..."
    ignore_require_venv = True

    def add_options(self) -> None:
        self.cmd_opts.add_option(
            "-a",
            "--algorithm",
            dest="algorithm",
            choices=STRONG_HASHES,
            action="store",
            default=FAVORITE_HASH,
            help="The hash algorithm to use: one of {}".format(
                ", ".join(STRONG_HASHES)
            ),
        )
        self.parser.insert_option_group(0, self.cmd_opts)

    def run(self, options: Values, args: List[str]) -> int:
        if not args:
            self.parser.print_usage(sys.stderr)
            return ERROR

        algorithm = options.algorithm
        for path in args:
            write_output(
                "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm)
            )
        return SUCCESS


def _hash_of_file(path: str, algorithm: str) -> str:
    """Return the hash digest of a file."""
    with open(path, "rb") as archive:
        hash = hashlib.new(algorithm)
        for chunk in read_chunks(archive):
            hash.update(chunk)
    return hash.hexdigest()
