#!/usr/bin/env python
# Copyright 2018 Digital Domain 3.0
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
#    names, trademarks, service marks, or product names of the Licensor
#    and its affiliates, except as required to comply with Section 4(c) of
#    the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
import os
import sys

import argparse

from qt_py_convert.run import process_file, process_folder
from qt_py_convert.general import WriteFlag


def parse():
    parser = argparse.ArgumentParser(
        "qt_py_convert"
    )

    parser.add_argument(
        "files_or_directories",
        nargs="+",
        help="Pass explicit files or a directories to run. "
             "NOTE: If \"-\" is passed instead of files_or_directories, "
             "qt_py_convert will attempt to read from stdin. "
             "Useful for pipelining processes"
    )
    parser.add_argument(
        "-r", "--recursive",
        action="store_true",
        help="Recursively search for python files to convert. "
             "Only applicable when passing a directory.",
    )
    parser.add_argument(
        "--stdout",
        action="store_true",
        help="Boolean flag which will write the resulting file to stdout "
             "instead of on disk."
    )
    parser.add_argument(
        "--write-path",
        required=False,
        default=None,
        help="If provided, QtPyConvert will treat \"--write-path\" as a "
             "relative root and write modified files from there."
    )
    parser.add_argument(
        "--backup",
        action="store_true",
        help="When combined with the \"--stdout\" flag it will not produce "
             "\"*.bak\" files for converted files.",
    )
    parser.add_argument(
        "--show-lines",
        action="store_true",
        help="Turn on printing the line numbers that things are replaced at. "
             "Ends up being much slower to process.",
    )
    parser.add_argument(
        "--to-method-support",
        action="store_true",
        help="EXPERIMENTAL: An attempt to replace all api1.0 style "
             "\"toString\", \"toInt\", \"toFloat\", \"toBool\", \"toPyObject\""
             ", \"toAscii\" methods that are unavailable in api2.0.",
    )
    parser.add_argument(
        "--explicit-signals-flag",
        action="store_true",
        help="EXPERIMENTAL: Modification on the api1.0 style signal conversion"
             " logic. It will explicitly slice into the QtCore.Signal object "
             "to find the signal with the matching signature.\n"
             "This is a fairly unknown feature of PySide/PyQt and is usually "
             "worked around by the developer. However, this should be safe to "
             "turn on whichever the case.",
    )

    return parser.parse_args()


def _resolve_stdin(paths):
    """
    _resolve_stdin allows us to have "-" in our files_or_directories and have
        it expand to input from stdin.
    This allows us to pipe into qt_py_convert.

    :param paths: List of strings. It wll replace any strings matching "-"
        with sys.stdin.
    :type paths: list[str...]
    :return: List that has been modified to include stdin.
    :rtype: list[str...]
    """
    _stdin = None
    _inserted = 0
    for index, path in enumerate(paths[:]):
        if path == "-":  # Insert stdin anytime we see "-"
            _index = index+_inserted  # Calculated index after insertions.
            paths.pop(_index)  # Remove the "-"
            if _stdin is None:  # If we haven't pulled from stdin yet.
                _stdin = [
                    x.strip("\n").strip("\r")  # Strip \n and \r
                    for x in list(sys.stdin)  # Iterate through stdin.
                ]
            # Generate a new list.
            # Basically if I could do an "insert" and an "expand" at once.
            paths = paths[:_index] + _stdin + paths[_index:]
            # We have inserted x - 1 because we popped.
            _inserted += len(_stdin) - 1
    return paths


def main(pathlist, recursive=True, path=None, no_write=False, backup=False, stdout=False, show_lines=True, tometh=False):
    # if len(pathlist) == 1:
    #     if pathlist[0] == "-":  # Support for piping on unix.
    #         pathlist = sys.stdin

    pathlist = _resolve_stdin(pathlist)

    output = 0
    if stdout:
        output |= WriteFlag.WRITE_TO_STDOUT
    else:
        output |= WriteFlag.WRITE_TO_FILE

    for src_path in pathlist:
        # print("Processing %s" % path)
        abs_path = os.path.abspath(src_path)
        if os.path.isdir(abs_path):
            process_folder(
                src_path,
                recursive=recursive,
                write_mode=output,
                path=(path, abs_path),
                backup=backup,
                skip_lineno=not show_lines,
                tometh_flag=tometh
            )
        else:
            process_file(
                src_path,
                write_mode=output,
                path=(path, abs_path),
                backup=backup,
                skip_lineno=not show_lines,
                tometh_flag=tometh
            )


if __name__ == "__main__":
    args = parse()
    main(
        pathlist=args.files_or_directories,
        recursive=args.recursive,
        path=args.write_path,
        backup=args.backup,
        stdout=args.stdout,
        show_lines=args.show_lines,
        tometh=args.to_method_support,
    )
