#!/usr/bin/env python
# Copyright (C) 2017 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# A webkitpy import needs to go first for autoinstaller to work with subsequent imports.
import webkitpy

import os
import six
import sys

REBASE_DICTIONARY = {
    'WebKit2/': 'WebKit/',
    'WebKit/': 'WebKitLegacy/'
}
class RebaseStatus:
    DO_NOT_NEED = 0
    MAYBE_NEED = 1
    NEED = 2
    ALREADY = 3


def append_source(path):
    return os.path.join('Source', path)


def is_editable_line(line):
    editable_prefixes = ('Index: ', '--- ', '+++ ', 'diff --git ')
    return any(map(line.startswith, editable_prefixes))


def needs_rebase(line):
    if not is_editable_line(line):
        return RebaseStatus.DO_NOT_NEED

    for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
        # Check if we've already rebased. We need to check if the rebased_name is already in the REBASE_DICTIONARY,
        # in this case, we don't know if we've already been rebased.
        if append_source(rebased_name) in line and rebased_name not in REBASE_DICTIONARY:
            return RebaseStatus.ALREADY

        # Check if we need to rebase. We need to check if the current name is one of the potential rebase names.
        # In this case, we don't know if we need the rebase.
        if append_source(current_name) in line and current_name not in REBASE_DICTIONARY.values():
            return RebaseStatus.NEED

    # Check if we might need a rebase
    for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
        if append_source(current_name) in line:
            return RebaseStatus.MAYBE_NEED

    return RebaseStatus.DO_NOT_NEED


def rebase_line(line):
    if not is_editable_line(line):
        for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
            if current_name in line:
                sys.stderr.write('Found an instance of {} in the patch.  Did you mean to replace it with {}?\n'.format(current_name, rebased_name))
        return line
    for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
        if append_source(current_name) in line:
            return line.replace(append_source(current_name), append_source(rebased_name))
    return line


def rebase(patch_content, output_file, patch_name):
    rebase_status = RebaseStatus.DO_NOT_NEED
    for line in patch_content:
        line_status = needs_rebase(line)
        if (rebase_status == RebaseStatus.NEED and line_status == RebaseStatus.ALREADY) or (rebase_status == RebaseStatus.ALREADY and line_status == RebaseStatus.NEED):
            sys.stderr.write('{} is a partially rebased patch\n'.format(patch_name))
            return -1
        rebase_status = max(rebase_status, line_status)

    if rebase_status == RebaseStatus.MAYBE_NEED and output_file == sys.stdout:
        sys.stderr.write('Cannot determine if path from {} has already been rebased, rebasing anyways\n'.format(patch_name))
    elif rebase_status == RebaseStatus.MAYBE_NEED:
        rebase_status = RebaseStatus.MAYBE_NEED
        sys.stdout.write('{} may have already been rebased, are you sure you want to rebase it Y/n?\n'.format(patch_name))
        line = sys.stdin.readline().rstrip().upper()
        if line == 'Y' or line == 'YES':
            rebase_status = RebaseStatus.NEED

    if rebase_status == RebaseStatus.ALREADY or rebase_status == RebaseStatus.MAYBE_NEED:
        # Output the provided patch if no re-base is required
        for line in patch_content:
            output_file.write(line)
        return 0

    if rebase_status == RebaseStatus.MAYBE_NEED:
        sys.stderr.write('Cannot determine if path from {} has already been rebased, rebasing anyways\n'.format(patch_name))

    for line in patch_content:
        output_file.write(rebase_line(line))

    return 0


def parse_arguments():
    files_to_rebase = []
    if len(sys.argv) == 1:
        sys.stderr.write('Reading patch from stdin\n')
        return []
    elif sys.argv[1] == '-h' or sys.argv[1] == 'help':
        print('rebase-patch-after-webkit-move usage:')
        print('\trebase-patch-after-webkit-move -h, help')
        print('\t\tPrint this message')
        print('\trebase-patch-after-webkit-move <path to patch>')
        print('\t\tReplace the patch at the provided path with a rebased patch')
        print('\trebase-patch-after-webkit-move')
        print('\t\tTreat stdin as the patch to be rebased')
        exit(0)

    for path in sys.argv[1:]:
        if not os.path.isfile(path):
            sys.stderr.write('{} does not exist, cannot rebase patch\n'.format(path))
            exit(1)
        files_to_rebase.append(path)

    return files_to_rebase


if __name__ == '__main__':
    files_to_rebase = parse_arguments()

    status = 0
    for path in files_to_rebase:
        if rebase(open(path, 'r').readlines(), open(path, 'w'), path) != 0:
            status = 1
    if not files_to_rebase:
        status = rebase(sys.stdin.readlines(), sys.stdout, 'STDIN')
    exit(status)
