#!/usr/bin/env python3

#
# Copyright (c) 2021 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import argparse
import os
import subprocess
import sys


def get_commit_sha(repository_location, rev):
    command = ['git', '-C', repository_location, 'rev-list', '-n', '1', rev]
    process = subprocess.run(command, check=True, stdout=subprocess.PIPE)
    return process.stdout.decode('ascii').strip()


def update_ncs(repository_location, revision, fetch_shallow):
    # Fetch sdk-nrf to the desired revision.
    command = ['git', '-C', repository_location, 'fetch']
    subprocess.run(command, check=True)

    # Checkout sdk-nrf to the desired revision.
    command = ['git', '-C', repository_location, 'checkout', revision]
    subprocess.run(command, check=True)

    # Call west update command to update all projects and submodules used by sdk-nrf.
    command = ['west', 'update']
    command += ['--fetch', 'smart', '--narrow',
                '-o=--depth=1'] if fetch_shallow else []
    subprocess.run(command, check=True)


def get_ncs_recommended_revision():
    chip_root = os.path.abspath(os.path.join(
        os.path.dirname(__file__), os.path.normpath('../../..')))

    # Read recommended revision saved in the .nrfconnect-recommended-revision file.
    try:
        with open(os.path.join(chip_root, 'config/nrfconnect/.nrfconnect-recommended-revision'), 'r') as f:
            return f.readline().strip()
    except:
        raise RuntimeError(
            "Encountered problem when trying to read .nrfconnect-recommended-revision file.")


def print_messages(messages: list, yellow_text: bool):
    # Add colour formatting if yellow text was set
    if yellow_text:
        messages = [f"\33[33m{message}\x1b[0m" for message in messages]

    for message in messages:
        print(message)


def print_check_revision_warning_message(current_revision, recommended_revision):
    current_revision_message = f"WARNING: Your current NCS revision ({current_revision})"
    recommended_revision_message = f"differs from the recommended ({recommended_revision})."
    allowed_message = "Please be aware that it may lead to encountering unexpected problems."
    update_message = "Consider updating NCS to the recommended revision, by calling:"
    call_command_message = os.path.abspath(__file__) + " --update"

    # Get the longest message lenght, to fit warning frame size.
    longest_message_len = max([len(current_revision_message), len(recommended_revision_message), len(
        allowed_message), len(update_message), len(call_command_message)])

    # To keep right frame shape the space characters are added to messages shorter than the longest one.
    fmt = "# {:<%s}#" % (longest_message_len)

    print_messages([(longest_message_len+3)*'#', fmt.format(current_revision_message), fmt.format(recommended_revision_message), fmt.format(''),
                    fmt.format(allowed_message), fmt.format(update_message), fmt.format(call_command_message), (longest_message_len+3)*'#'], sys.stdout.isatty())


def main():

    try:
        zephyr_base = os.getenv("ZEPHYR_BASE")
        if not zephyr_base:
            raise RuntimeError(
                "No ZEPHYR_BASE environment variable found, please set ZEPHYR_BASE to a zephyr repository path.")

        parser = argparse.ArgumentParser(
            description='Script helping to update nRF Connect SDK to currently recommended revision.')
        parser.add_argument(
            "-c", "--check", help="Check if your current nRF Connect SDK revision is the same as recommended one.", action="store_true")
        parser.add_argument(
            "-u", "--update", help="Update your nRF Connect SDK to currently recommended revision.", action="store_true")
        parser.add_argument(
            "-s", "--shallow", help="Fetch only specific commits (without the history) when updating nRF Connect SDK.", action="store_true")
        parser.add_argument(
            "-q", "--quiet", help="Don't print any message if the check succeeds.", action="store_true")
        args = parser.parse_args()

        ncs_base = os.path.join(zephyr_base, '../nrf')
        recommended_revision = get_ncs_recommended_revision()

        if args.check:
            if not args.quiet:
                print("Checking current nRF Connect SDK revision...")

            current_sha = get_commit_sha(ncs_base, 'HEAD')
            recommended_sha = get_commit_sha(ncs_base, recommended_revision)

            if current_sha != recommended_sha:
                print_check_revision_warning_message(
                    current_sha, recommended_sha)
                sys.exit(1)

            if not args.quiet:
                print("Your current version is up to date with the recommended one.")

        if args.update:
            print("Updating nRF Connect SDK to recommended revision...")
            update_ncs(ncs_base, recommended_revision, args.shallow)

    except (RuntimeError, subprocess.CalledProcessError) as e:
        print(e)
        sys.exit(1)


if __name__ == '__main__':
    main()
