#!/usr/bin/env/python3

'''
Copyright 2017, Fujitsu Network Communications, Inc.
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 sys
import os
import re
import ast
import time
import argparse
import subprocess
from datetime import datetime

"""
This script add the user repository name according to the drivers in Testcase file and adds
the import statements according to repo
This script requires arguments to run

add Repo name under step section in Testcase:
ex : pre = <Step Driver="cli_driver" Keyword="connect">
    after = <Step Driver="cli_driver" Repo="warrior" Keyword="connect">

    for acheving this we need to pass arguments as:
    1. for finding drivers need warriorsapce directory/bitbucket url
        python warrior_py3_migration_tool.py --add_repo_war_repos_path "directory"
        python warrior_py3_migration_tool.py --add_repo_warrior_url "bitbucket url"
    2. for finding repo names need keywords directory/bitbucket url of keywords
        python warrior_py3_migration_tool.py --add_repo_kw_repos_path "directory"
        python warrior_py3_migration_tool.py --add_repo_keyword_url "bitbucket_url1 bitbucket_url2"
    3. if need to provide the dir/results directory
        --add_repo_output_dir "dir to store results"

Verify import statemts in keywords user repository:
ex : pre = import Framework.Utils.print_info
    after = import warrior.Framework.Utils.print_info

    1.for finding keywords need keywords directory/bitbucket url
        python warrior_py3_migration_tool.py --imp_user_repo_path "directory"
        python warrior_py3_migration_tool.py --imp_url "bitbucket url"
    2. if need to provide the path dir/results directory
        --imp_user_repo_path "dir to store results"
"""

CURRENT_WORKING_DIRECTORY = os.getcwd()

WARRIOR_ACTIONS = ["CiRegressionActions", "CliActions", "CloudshellActions", "CommonActions",
                   "DemoActions", "ExampleActions", "FileActions", "GnmiActions", "KafkaActions",
                   "LogActions", "NetconfActions", "NetworkActions", "RestActions",
                   "SeleniumActions", "ServerActions", "SnmpActions", "WappActions"]
WARRIOR_ACTIONS_CLASSES = ["ci_regression_actions", "cli_actions", "cloudshell_actions",
                           "common_actions", "demo_actions", "example_actions", "file_actions",
                           "gnmi_actions", "kafka_actions", "log_actions", "netconf_Actions",
                           "connection_actions", "diagnostics_actions", "file_ops_actions",
                           "rest_actions", "browser_actions", "elementlocator_actions",
                           "elementoperation_actions", "verify_actions", "wait_actions",
                           "server_actions", "common_snmp_actions", "wapp_reporting_actions"]
WARRIOR_UTILS = ["cli_Utils", "config_Utils", "csv_Utils", "data_Utils", "datetime_utils",
                 "demo_utils", "dict_Utils", "driver_Utils", "email_utils", "encryption_utils",
                 "file_Utils", "import_utils", "list_Utils", "print_Utils", "rest_Utils",
                 "selenium_Utils", "snmp_utils", "string_Utils", "telnet_Utils", "testcase_Utils",
                 "xml_Utils"]
WARRIOR_FRAMEWORK_CLASSES = ["configuration_element_class", "database_utils_class",
                             "gnmi_utils_class", "json_utils_class", "kafka_utils_class",
                             "netconf_utils_class", "rest_server_class", "rest_utils_class",
                             "snmp_utility_class", "ssh_util_class", "testdata_class",
                             "xl_utils_class"]
BUILTIN_MODULES = ["os", "collections", "pexpect", "time", ""]
WARRIOR_CLI_UTILS = ["base_class", "connection", "diagnostics", "file_ops", "loging",
                     "network_class", "warrior_cli_class"]


def print_info(message, *args):
    """Print an info message to the terminal """
    print_type = "-I-"
    if len(args) > 0:
        for arg in args:
            message += str(arg) + ", "
    color_message = None
    

    print_main(message, print_type, color_message)
    return message

def print_main(message, print_type, color_message=None, *args, **kwargs):
    """The main print function will be called by other print functions
    """
    if color_message is not None:
        print_string = print_type + " " + str(color_message)
    elif color_message is None:
        print_string = print_type + " " + str(message)
    if args:
        print_string = (print_type + " " + str(message) + str(args))

    sys.stdout.write(print_string + '\n')


class addRepoinStepSection():
    """
    This class will adds the repo name under xml files
    """

    def __init__(self, warrior_repo=None, Keyword_repos=None, add_repo_output=None,
        add_repo_war_repos_path=None, add_repo_kw_repos_path=None):
        """
        This init function will accept the parameters 
        """
        self.warrior_repo = warrior_repo
        self.keyword_repos = Keyword_repos
        self.add_repo_output = add_repo_output
        self.add_repo_war_repos_path = add_repo_war_repos_path
        self.add_repo_kw_repos_path = add_repo_kw_repos_path
        self.numbers_dict = {"1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six",
                             "7": "seven", "8": "eight", "9": "nine"}

    def add_repo_in_step(self):
        '''
        This definition will add the repo name under the step section
        '''
        if self.add_repo_war_repos_path:
            print_info("add_repo_war_repos_path", self.add_repo_war_repos_path)
            path = self.add_repo_war_repos_path
        else:
            path = self.warr_repo_name
        print_info("Provided path :", path)
        print_info("Finding the xml files.....")
        for root, _, files in os.walk(path):
            for file in files:
                if file.endswith('.xml'):

                    #heare opening the file which ends with .xml
                    with open((root +"/"+ file), "r") as reading_file:
                        print_info("Found the xml file to read", file)
                        lines = reading_file.read()

                        stp = re.findall('<step Driver="([a-zA-Z0-9_]+)" Keyword=', lines)
                        self.drivers = list(set(stp))

                        #heare passing the driver to the get_repo_name definition and
                        # collecting the dictionary
                        repo_driver_dict = self.get_repo_name()

                        print_info("Adding the repo name under step section")

                        #heare adding the repo in mathced places
                        for driver_item in repo_driver_dict:
                            if repo_driver_dict[driver_item] != "warroir":
                                exist_str = '<step Driver="%s"' % driver_item
                                new_str = '<step Driver="%s" Repo="%s"' %(
                                    driver_item, repo_driver_dict[driver_item])
                                lines = re.sub(exist_str, new_str, lines)

                    #here writing modified lines into .xml file
                    with open((root +"/"+ file), "w") as writing_file:
                        writing_file.write(lines)
        print_info("successfully completed the adding Repo under all Testcase files.")
        print_info("The results present in ", self.add_repo_output)


    def get_repo_name(self):
        '''
        In this function finding the repo name of respective drivers
        '''
        path = self.add_repo_output
        driver_repo_dict = {}

        for driver in self.drivers:
            print_info("Found the Driver present in xml file", driver)
            driver_file = driver+".py"
            for root, _, files in os.walk(path):
                for file in files:
                    if file.endswith('.py') and file != "__init__.py":
                        if file == driver_file:
                            driver_repo = (os.path.abspath(os.path.join(root, os.pardir)))
                            driver_repo_name = driver_repo.split('/')[-1]
                            driver_repo_dict[driver] = driver_repo_name
                            print_info("Found the repo name of the Driver", driver_repo_name)
        return driver_repo_dict


    def repo_clone(self):
        """This definition will do the cloning the repo in the output directory  """

        self.warrior_repo_name = self.warrior_repo.split("/")[-1].split(".")[0]
        keyword_repo_names = ast.literal_eval(self.keyword_repos)
        keyword_repo_name = ", ".join(repr(e) for e in keyword_repo_names)
        self.all_kw_repos_names = []
        repo_names = keyword_repo_name.split(' ')
        for repo in repo_names:
            rep = repo.replace('"', '').replace("'", '')
            kw_dir_name = rep.split("/")[-1].split(".")[0]
            self.all_kw_repos_names.append(kw_dir_name)

        print_info("warrior_repo_name", self.warrior_repo_name)
        print_info("all_kw_repos_names", self.all_kw_repos_names)

        def get_immediate_subdirectories_in_output_dir(self):
            """
            this function will finds the sub dirs present in the output directory
            """
            try:
                current_wkdir = os.getcwd()
                print_info("current working directory is", current_wkdir)

                dir_names = []
                counter = 0
                for name in os.listdir(current_wkdir):
                    dir_names.append(name)
                    counter = counter + 1

                for dir_name in dir_names:
                    if dir_name == self.warrior_repo_name:
                        self.war_dir_path = os.getcwd()+"/"+dir_name
                        print_info("warrior directory path is ", self.war_dir_path)
                return self.war_dir_path
            except Exception as ex_er:
                print_info("No cloned repos are presented in current directory!!!")
                print_info("Error is ", ex_er)


        if self.add_repo_output == None:
            new_dir = os.path.join(os.getcwd(),
                                   "Add_repo_name_"+datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))

            try:
                os.mkdir(new_dir)
                os.chdir(new_dir)
                self.add_repo_output = os.getcwd()
                print_info("Created result directory is ", self.add_repo_output)
                print_info("**************************************************************************"
                      "****")
                print_info("Result directory is ", new_dir)
                print_info("**************************************************************************"
                      "****")
            except Exception as ex_er:
                print_info("directory already present. Please try with different!!!", ex_er)

        try:
            out_dir = self.add_repo_output
            os.chdir(out_dir)
            print_info("Provided output directory is", self.add_repo_output)
            print_info("******************************************************************************")
            print_info("Result directory is ", os.getcwd())
            print_info("******************************************************************************")
        except Exception as ex_er:
            print_info("provded directory is not present. Please try with diffrent directory!!!")
            print_info("Erropr is ", ex_er)
            raise

        try:
            print_info(" warrior repo is ", self.warrior_repo)
            print_info("cloning Warror/warroirspace repository. Please wait....")
            war_repo_name  = self.warrior_repo.split("/")[-1].split(".")[0]
            pattern3 = r'(\d)'
            match3 = re.match(pattern3, war_repo_name)
            match_flag3 = False
            if match3:
                existing_name = war_repo_name
                mod_path = "{}{}".format(self.numbers_dict[match3.group(1)], war_repo_name.split(match3.group(1))[-1])
                match_flag3 = True
                war_repo_name = mod_path
            self.warr_repo_name = os.path.join(os.getcwd(), war_repo_name)
            if os.path.exists(os.path.join( self.add_repo_output, war_repo_name)):
                timestamp = time.time()
                new_directory_name = "{}_{}".format(war_repo_name, int(timestamp))
                pattern = r'(\d)'
                match7 = re.match(pattern, new_directory_name)
                match_flag7 = False
                if match7:
                    existing_name = new_directory_name
                    mod_path = "{}{}".format(self.numbers_dict[match7.group(1)], new_directory_name.split(
                        match7.group(1))[-1])
                    match_flag7 = True
                    new_directory_name = mod_path
                self.add_repo_output = os.path.join(self.add_repo_output, new_directory_name)
                os.mkdir(self.add_repo_output)
            gitimpo.Git(self.add_repo_output).clone(self.warrior_repo)
            if match_flag3:
                os.system("mv {}/ {}".format(existing_name, mod_path))
            print_info("successfully cloned Warror/warroirspace repository")
            print_info("cloning Keywords repositories")

            list_kw_urls = self.keyword_repos.split(" ")
            all_kw_dirs = []
            i = 0
            for _ in list_kw_urls:
                kw_url = list_kw_urls[i]
                u_r_l = kw_url.replace('[', '').replace(']', '').replace("'", '').replace(',', '')
                # repo_name = kw_url.split("/")[-1].split(".")[0]
                print_info("cloning the warrior Keyword repo. Please wait....")
                print_info("clong repo is ", u_r_l)
                kw_repo_name = u_r_l.split("/")[-1].split(".")[0]
                gitimpo.Git(self.add_repo_output).clone(u_r_l)

                pattern4 = r'(\d)'
                match4 = re.match(pattern4, kw_repo_name)
                match_flag4 = False
                if match4:
                    existing_name = kw_repo_name
                    mod_path = "{}{}".format(self.numbers_dict[match4.group(1)],
                                             kw_repo_name.split(match4.group(1))[-1])
                    match_flag4 = True
                    kw_repo_name = mod_path
                if os.path.exists(os.path.join( self.add_repo_output, kw_repo_name)):
                    timestamp = time.time()
                    new_directory_name = "{}_{}".format(kw_repo_name, int(timestamp))
                    new_path = os.path.join(self.add_repo_output, new_directory_name)
                    os.mkdir(new_path)
                    all_kw_dirs.append(u_r_l)
                    if match_flag4:
                        os.system("mv {}/ {}".format(existing_name, new_directory_name))
                        os.chdir(os.path.join(os.getcwd(), new_directory_name))

                        pattern5 = r'(\d)'
                        match5 = re.match(pattern5, os.path.split(os.path.join(os.getcwd(), existing_name))[-1])
                        match_flag5 = False
                        if match5:
                            new_directory_name = existing_name
                            mod_path = "{}{}".format(self.numbers_dict[match5.group(1)],
                                                     new_directory_name.split(match5.group(1))[-1])
                            match_flag5 = True

                        if match_flag5:
                            os.system("mv {}/ {}".format(existing_name, mod_path))

                else:
                    if match_flag4:
                        os.system("mv {}/ {}".format(existing_name, mod_path))

                print_info("successfully cloned Warror Keyword repo", u_r_l)
                i = i+1
            print_info("successfully cloned Keywords repository(s)!!")
        except Exception as ex_er:
            print_info("################################################################")
            print_info("repository(s) alredy present in this directory")
            print_info("#################################################################")
            print_info("Error ", ex_er)
            sys.exit()
        self.add_repo_in_step()

class Verify_Import_Statements():
    """
    This class will verify the imports present user repo
    """

    def __init__(self, user_repo_path):

        """
        This init function will accept the parameters 
        """
        self.user_repo_path = user_repo_path
        self.numbers_dict = {"1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six",
                        "7": "seven", "8": "eight", "9": "nine"}

    def check_for_statement_is_available_in_user_repo(self, line, user_repo_path):
        """
        This function will checks the statemnts are present in the user repo or not
        :param line:
        :param user_repo_path:
        :return:
        """
        self.user_repo_path = user_repo_path

        line = line.strip()
        if line.startswith("from"):
            import_words = line.split()[1].split(".")
            after_imports = line.split()[-1]
            if "," in after_imports:
                after_imports = after_imports.split(",")[-1]
            else:
                pass
            if after_imports in WARRIOR_UTILS:
                return "warrior"

            abs_path = "/".join(import_words)
            actual_path = os.path.join(self.user_repo_path, abs_path)
            directory_name = os.path.split(self.user_repo_path)[-1]
            if os.path.exists(actual_path) or os.path.exists("{}.py".format(actual_path)):
                return directory_name
            else:
                return "warrior"
        elif line.strip().startswith("import"):
            import_words = line.strip("import").strip().split(".")
            abs_path = "/".join(import_words)
            actual_path = os.path.join(self.user_repo_path, abs_path)
            directory_name = os.path.split(self.user_repo_path)[-1]
            if os.path.exists(actual_path) or os.path.exists("{}.py".format(actual_path)):
                return directory_name
            else:
                return "warrior"
        else:
            return "not valid"

    def verify_import_statements(self, user_repo_path):
        """
        This function will verify the imports present in the provided repo/path
        :param user_repo_path:
        :return:
        """
        self.user_repo_path = user_repo_path
        if os.path.exists(self.user_repo_path):
            directory_name = os.path.split(self.user_repo_path)[-1]
            for root, _, files in os.walk(self.user_repo_path):
                if root.endswith(directory_name) and "__init__py" not in files:
                    cmd = "touch  {}/__init__.py".format(self.user_repo_path)
                    os.system(cmd)

                for file in files:

                    if file == "__init__.py":
                        pass
                    elif file.endswith(".py"):

                        filedesc = open(root + "/" + file, "r+")
                        file_lines = filedesc.readlines()
                        for fline in file_lines:
                            if fline.startswith("class"):
                                break
                            if (fline.startswith("import")  or fline.startswith("from")) and "*" in fline :
                                print_info("Not found  statement {} in user repo or warrior and file name {}".
                                           format(fline.strip(), file))
                            elif fline[:-1] == "import Framework.Utils as Utils" or re.search(
                                    r"\s*import Framework.Utils as Utils", fline[:-1]):
                                fline = fline[:-1]
                                impo = "sed -i 's/import Framework.Utils as Utils/import " \
                                    "warrior.Framework.Utils as Utils/g' {}".format(
                                        root + "/" + file)
                                os.system(impo)
                            elif fline[:-2] == "import Framework.Utils as Utils" or re.search(
                                    r"\s*import Framework.Utils as Utils", fline[:-2]):
                                fline = fline[:-2]
                                impo = "sed -i 's/import Framework.Utils as Utils/import " \
                                    "warrior.Framework.Utils as Utils/g' {}".format(
                                        root + "/" + file)
                                os.system(impo)
                            elif "Framework" in fline:
                                if "\r" in fline:
                                    fline = fline[:-2]
                                else:
                                    fline = fline[:-1]
                                repo_name = self.check_for_statement_is_available_in_user_repo(
                                    fline, self.user_repo_path)
                                if repo_name == "warrior":
                                    warrior_flag = True
                                    user_repo_flag = False
                                    other_flag = True
                                elif repo_name == "not valid":
                                    other_flag = False
                                else:
                                    user_repo_flag = True
                                    warrior_flag = False
                                    other_flag = True

                                if "from" in fline:
                                    chg = fline.split("from")[1]
                                    if chg.strip().startswith("Framework"):
                                        portt = fline.split("import")[0].strip().split(".")[-1]
                                        if (portt in WARRIOR_UTILS or portt in WARRIOR_CLI_UTILS) and \
                                                warrior_flag:
                                            ffline = re.sub("Framework", "warrior.Framework",
                                                            fline, 1)
                                            impo = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file, )
                                            os.system(impo)
                                        elif fline.split()[-1] in WARRIOR_UTILS and warrior_flag:
                                            ffline = re.sub("Framework", "warrior.Framework",
                                                            fline, 1)
                                            a = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file, )
                                            os.system(a)
                                        elif fline.split(".")[-1].split()[0] in \
                                                WARRIOR_FRAMEWORK_CLASSES and warrior_flag:
                                            ffline = re.sub("Framework", "warrior.Framework",
                                                            fline, 1)
                                            a = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file, )
                                            os.system(a)

                                        elif user_repo_flag:
                                            ffline = re.sub("Framework",
                                                            "{}.Framework".format(directory_name),
                                                            fline, 1)
                                            a = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file)
                                            os.system(a)
                                        elif other_flag:
                                            print_info("Not found  statement "
                                                  "{} in user repo or warrior and file name {}".
                                                  format(fline.strip(), file))

                            elif "Actions" in fline:
                                if "\r" in fline:
                                    fline = fline[:-2]
                                else:
                                    fline = fline[:-1]
                                repo_name = self.check_for_statement_is_available_in_user_repo(
                                    fline, self.user_repo_path)
                                if repo_name == "warrior":
                                    warrior_flag = True
                                    user_repo_flag = False

                                else:
                                    user_repo_flag = True
                                    warrior_flag = False
                                if "from" in fline:
                                    cd = fline.split("from")[1]
                                    if cd.strip().startswith("Actions"):
                                        aa = fline.split("import")[0].strip().split(".")[-1]
                                        if aa in WARRIOR_ACTIONS or aa in \
                                                WARRIOR_ACTIONS_CLASSES and warrior_flag:
                                            ffline = re.sub("Actions", "warrior.Actions", fline, 1)
                                            a = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file)
                                            os.system(a)
                                        elif user_repo_flag:
                                            ffline = re.sub("Actions", "{}.Actions".format(
                                                directory_name), fline, 1)
                                            a = """sed -i 's/{}/{}/g' {}""".format(
                                                fline, ffline, root + "/" + file)
                                            os.system(a)
                                        else:
                                            print_info("not able too find {} and file {}".format(
                                                fline, file))
                                elif fline.startswith("import"):
                                    if fline.split(".")[-1] in WARRIOR_ACTIONS and warrior_flag:
                                        ffline = re.sub("Actions", "warrior.Actions".format(
                                            directory_name), fline, 1)
                                        a = """sed -i 's/{}/{}/g' {}""".format(
                                            fline, ffline, root + "/" + file)
                                        os.system(a)
                                    elif user_repo_flag:
                                        ffline = re.sub("Actions", "{}.Actions".format(
                                            directory_name), fline, 1)
                                        a = """sed -i 's/{}/{}/g' {}""".format(
                                            fline, ffline, root + "/" + file)
                                        os.system(a)
                                    else:

                                        print_info("not able to find {} and file {}".format(fline,
                                                                                       file))
                                else:
                                    if "[Actions" in fline:
                                        pattern = r"\s*package_list\s*\=\s*\[Actions.*\.(\w+)\]"
                                        match = re.search(pattern, fline)
                                        fline = fline.replace("[", r"\[")
                                        if match:
                                            if match.group(1) in WARRIOR_ACTIONS:
                                                ffline = re.sub("Actions", "warrior.Actions".format(
                                                    directory_name), fline, 1)
                                                awe = """sed -i 's/{}/{}/g' {}""".format(
                                                    fline.strip(), ffline.strip(),
                                                    root + "/" + file)
                                                os.system(awe)
                                            else:
                                                ffline = re.sub("Actions", "{}.Actions".format(
                                                    directory_name), fline, 1)
                                                af = """sed -i 's/{}/{}/g' {}""".format(
                                                    fline.strip(), ffline.strip(),
                                                    root + "/" + file)
                                                os.system(af)

                            elif "WarriorCore" in fline:
                                if fline.startswith("WarriorCore"):
                                    if "\r" in fline:
                                        fline = fline[:-2]
                                    else:
                                        fline = fline[:-1]
                                    ffline = re.sub("WarriorCore", "warrior.WarriorCore", fline, 1)
                                    a = """sed -i 's/{}/{}/g' {}""".format(
                                        fline, ffline, root + "/" + file)
                                    os.system(a)
                                else:
                                    if "\r" in fline:
                                        fline = fline[:-2]
                                    else:
                                        fline = fline[:-1]
                                    ffline = re.sub("WarriorCore", "warrior.WarriorCore", fline, 1)
                                    a = """sed -i 's/{}/{}/g' {}""".format(
                                        fline, ffline, root + "/" + file)
                                    os.system(a)


        else:
            print_info("path not found")

#Argparser to add command line argumets
parser = argparse.ArgumentParser()
parser.add_argument('--imp_url', "-iu", type=str, help="git/bitbucket keyword repository cloning url only")
parser.add_argument('--imp_output_dir', "-iod", type=str, help="to store the output directory ")
parser.add_argument('--imp_user_repo_path', "-iurp", type=str,
                    help="user repo name including absolute path")

parser.add_argument("--add_repo_warrior_url", "-arwu", type=str,
                    help="Enter the absolute url link of user repository of "
                    "Warrorspace/xml files")
parser.add_argument("--add_repo_keyword_url", "-arku", nargs='*', type=str,
                    help="Enter the absolute url link of user repository of Keyword files")
parser.add_argument("--add_repo_output_dir", "-arod", type=str,
                    help="Enter the absolute path to create output directory")
parser.add_argument("--add_repo_war_repos_path", "-arwrp", type=str,
                    help="Enter the absolute path to create output directory")
parser.add_argument("--add_repo_kw_repos_path", "-arkrp", type=str,
                    help="Enter the absolute path to create output directory")

args = parser.parse_args()

imp_url = args.imp_url
imp_output_dir = args.imp_output_dir
user_repo_path = args.imp_user_repo_path

warrior_repo = args.add_repo_warrior_url
keyword_repos = args.add_repo_keyword_url
add_repo_war_repos_path = args.add_repo_war_repos_path
add_repo_kw_repos_path = args.add_repo_kw_repos_path
add_repo_output = args.add_repo_output_dir


class pre_requirements():
    """
    This class is the stating of the tools
    """

    def __init__(self, warrior_repo=None, keyword_repos=None, add_repo_output=None, imp_url=None,
                 user_repo_path=None, imp_output_dir=None, add_repo_war_repos_path=None,
                 add_repo_kw_repos_path=None):
        """
        This init function will accept the parameters 
        """
        self.warrior_repo = warrior_repo
        self.keyword_repos = keyword_repos
        self.add_repo_output = add_repo_output
        self.add_repo_war_repos_path = add_repo_war_repos_path
        self.add_repo_kw_repos_path = add_repo_kw_repos_path

        self.imp_url = imp_url
        self.user_repo_path = user_repo_path
        self.imp_output_dir = imp_output_dir
        self.numbers_dict = {"1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six",
                             "7": "seven", "8": "eight", "9": "nine"}

    def check_packages(self, str_package):
        """ Checks if the specified python package is installed.
        return type: boolean
        :Arguments:
        1. str_package (str) = name of the package to be checked
        :Returns:
        bool = True/False
        """
        try:
            import imp
            imp.find_module(str_package)
            bool_found = True
        except ImportError:
            bool_found = False
        return bool_found

    def check_git_status(self):
        """
        this function is for checking the status of the git
        """
        try:
            null = open("/dev/null", "w")
            sp_output = subprocess.Popen("git", stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE,
                                         stdin=subprocess.PIPE, shell=True)
            null.close()
            output = sp_output.stdout.read()
            print_info(output)
            return True

        except OSError:
            return False

    def activate_virtualenv(self):
        '''Activate virtual environment to add dependencies
        '''
        virt_name = "namespace_venv"
        ve_dest = os.path.join(CURRENT_WORKING_DIRECTORY, virt_name)
        print_info("ve_name: "+virt_name, )
        print_info("destination: "+ve_dest,)
        try:
            venv_cmd = os.path.expanduser("~/.local/bin/virtualenv")
            subprocess.check_call([venv_cmd, "--system-site-packages", ve_dest])
            venv_file = "{}/bin/activate_this.py".format(ve_dest)
            exec(compile(open(venv_file).read(), venv_file, 'exec'), dict(__file__=venv_file))
            return True
        except Exception as e:
            print_info("Activating virtual env at {} resulted in exception {}".format\
                (ve_dest, e))
            return False

    def install_depen(self, dependency, dependency_name):
        """ This function checks if a dependency was installed. If not,
         then it raises an error.
        """
        counter = 0
        if dependency == "virtualenv":
            os.system("python3 -m pip install --user virtualenv")
            time.sleep(5)
        pip_cmds = ['pip3', 'install', dependency]

        try:
            print_info("installing "+dependency)
            sp_output = subprocess.Popen(pip_cmds, stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE, stdin=subprocess.PIPE)

            output, error = sp_output.communicate()
            output = output.decode("utf-8")

            if "Requirement already satisfied" in output or "Successfully installed GitPython"\
             in output:
                print_info(" was able to install " + dependency_name)
                return True
            return_code = sp_output.returncode
            if return_code > 0:
                print_info(output, error)
        except IOError:
            counter = 1
            print_info("unable to install " + dependency_name)
        except:
            counter = 1
            print_info("unable to install " + dependency_name)
        if counter == 0:
            try:
                sp_output = subprocess.Popen(["pip", "show", dependency_name],
                                             stdin=subprocess.PIPE,
                                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                output = sp_output.stdout.read()
                if output == "":
                    print_info(dependency_name + " could not be installed!!")
                else:
                    print_info(dependency_name + " installation complete!")
            except:
                print_info("wasn't able to determine if " + dependency_name)

    def add_repo_in_step_repos(self):
        """
        This function will adds the repo name coresponding to the drivers in the xml files
        :return:
        """
        if (self.add_repo_war_repos_path and self.add_repo_kw_repos_path and
                self.add_repo_output) or (self.add_repo_war_repos_path and
                                          self.add_repo_kw_repos_path):

            print_info("Got the user repo paths. proceeding further!!")
            print_info("add_repo_war_repos_path is ", self.add_repo_war_repos_path)
            if self.add_repo_output:
                try:
                    rep = self.add_repo_war_repos_path.split("/")[-1]
                    print_info("Provided output path is", self.add_repo_output)
                    os.system("cp -r {} {}".format(self.add_repo_war_repos_path,
                                                   self.add_repo_output))
                    self.add_repo_war_repos_path = self.add_repo_output+"/"+rep
                    repos_paths = self.add_repo_kw_repos_path.split(" ")
                    list_of_keywords = []
                    for repo_kw in repos_paths:
                        rep = repo_kw.split("/")[-1]
                        os.system("cp -r {} {}".format(repo_kw, self.add_repo_output))
                        elem = str(self.add_repo_output)+"/"+str(rep)
                        list_of_keywords.append(elem)
                    self.add_repo_kw_repos_path = list_of_keywords
                except Exception as err:
                    print_info("Please provider correct output directory!!")
                    print_info("Error is ", err)
            else:
                new_dir = os.path.join(os.getcwd(),
                                       "Add_repo_name_in_repos"
                                       +datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))

                try:
                    os.mkdir(new_dir)
                    os.chdir(new_dir)
                    self.add_repo_output = os.getcwd()
                    try:
                        rep = self.add_repo_war_repos_path.split("/")[-1]
                        print_info("Provided output path is", self.add_repo_output)
                        os.system("cp -r {} {}".format(self.add_repo_war_repos_path,
                                                       self.add_repo_output))
                        self.add_repo_war_repos_path = self.add_repo_output+"/"+rep

                        repos_paths = self.add_repo_kw_repos_path.split(" ")
                        key_repo_path = []
                        for repo_kw in repos_paths:
                            rep = repo_kw.split("/")[-1]
                            os.system("cp -r {} {}".format(repo_kw, self.add_repo_output))
                            keywrd = str(self.add_repo_output)+"/"+str(rep)
                            key_repo_path.append(keywrd)
                        self.add_repo_kw_repos_path = key_repo_path

                    except Exception as err:
                        print_info("Please provider correct output directory!!")
                        print_info("Error is ", err)

                    print_info("Created result directory is ", self.add_repo_output)
                    print_info("***********************************************************************"
                          "*******")
                    print_info("Result directory is ", new_dir)
                    print_info("***********************************************************************"
                          "*******")
                except Exception as err:
                    print_info("directory already present. Please try with different!!!", err)

            Repo_adding = addRepoinStepSection(self.warrior_repo, self.keyword_repos,
                                               self.add_repo_output,
                                               self.add_repo_war_repos_path,
                                               self.add_repo_kw_repos_path)
            Repo_adding.add_repo_in_step()
            sys.exit()

    def add_repo_in_step_starts(self):
        """
        this function is the starting of the adding repo under xml files
        """

        print_info("Got user repo urls. proceeding further!!")
        print_info("Provided warroir repository link is ", self.warrior_repo)
        print_info("Provided Keywords repository link is ", self.keyword_repos)

        flag = False
        packages = ["pip", "git"]
        if self.warrior_repo and self.keyword_repos:
            flag = True
            if hasattr(sys, 'real_prefix'):
                pass
                git_status = self.check_git_status()
                if git_status:
                    print_info("Git is available proceeding further ")
                else:
                    print_info("Git is not installed on the system. "
                          "Please install git and restart this installation.")
                self.install_depen("GitPython", "git")
                import git as gitimpo
                global gitimpo
            else:
                bool_found = self.check_packages("pip")
                if not bool_found:
                    print_info("pip is not installed ")
                else:
                    print_info("pip is installed proceeding further !!!")
                git_status = self.check_git_status()
                if git_status:
                    print_info("Git is available proceeding further ")
                else:
                    print_info("Git is not installed on the system. "
                          "Please install git and restart this installation.")
                self.install_depen("virtualenv", "virtualenv")
                self.activate_virtualenv()
                self.install_depen("GitPython", "git")
                import git as gitimpo
                global gitimpo


        Repo_adding = addRepoinStepSection(self.warrior_repo, self.keyword_repos,
                                           self.add_repo_output)
        Repo_adding.repo_clone()

    def verify_import_statements_starts(self):
        """
        This function will adds the imports according to the repositories
        :return:
        """
        if self.imp_url:
            print_info("got url as argument ..proceeding further ")

        elif self.user_repo_path:

            print_info("got user_repo_path as argument ..proceeding further ")
            verify = Verify_Import_Statements(self.user_repo_path)
            if self.imp_output_dir:
                if os.path.exists(self.imp_output_dir):
                    pass
                else:
                    print_info("given path not found ")
                    sys.exit()

                parent_dir = self.user_repo_path.split("/")
                parent_path = "/".join(parent_dir[:-1])
                os.chdir(parent_path)
                os.system("rm -rf results_time")
                new_dir = "results_time"
                os.mkdir("results_time")
                os.system("cp -r {} {}".format(self.user_repo_path.split("/")[-1], new_dir))
                wew = "{}/{}".format(new_dir, parent_dir[-1])
                self.user_repo_path = os.path.join(os.getcwd(), wew)
            verify.verify_import_statements(self.user_repo_path)
            if self.imp_output_dir:
                text = self.user_repo_path.split("/")
                final_path = "/".join(text[:-1])
                os.system("mv {} {}".format(final_path, self.imp_output_dir))
                os.system("rm -rf results_time")
                print_info("The results are stored in {}".format(
                    os.path.join(self.imp_output_dir, text[-2], text[-1])))
            else:
                print_info("The results are stored in {}".format(self.user_repo_path))
        else:
            sys.exit("Need  at least one argument from the user cloning url or user repo path")

        flag = False
        packages = ["pip", "git"]
        if self.imp_url:
            flag = True
            if hasattr(sys, 'real_prefix'):
                git_status = self.check_git_status()
                if git_status:
                    print_info("Git is available proceeding further ")
                else:
                    print_info("Git is not installed on the system. "
                          "Please install git and restart this installation.")
                    sys.exit("Git is mandatory Please install it")
                dep_install_status = self.install_depen("GitPython", "git")
                if dep_install_status:
                    print_info("Successfully installed package {}".format("GitPython"))
                else:
                    print_info("Not able to install the package {}".format("GitPython"))
                import git
                path = self.imp_url.split("/")[-1].split(".")[0]

                pattern = r'(\d)'
                match9 = re.match(pattern, path)
                match_flag9 = False
                if match9:
                    existing_name= path
                    mod_path = "{}{}".format(self.numbers_dict[match9.group(1)], path.split(match9.group(1))[-1])
                    match_flag9 = True
                    path = mod_path

                user_dir_path_flag = False
                if self.imp_output_dir:
                    self.user_repo_path = self.imp_output_dir
                    if os.path.exists(self.user_repo_path):
                        os.chdir(self.user_repo_path)
                    else:
                        print_info("the provided path {} is not found ".format(self.user_repo_path))
                        sys.exit()
                elif os.path.exists(os.path.join(CURRENT_WORKING_DIRECTORY, path)):
                    user_dir_path_flag = True
                    import time
                    timestamp = time.time()
                    new_directory_name = "{}_{}".format(path, int(timestamp))
                    self.user_repo_path = os.path.join(CURRENT_WORKING_DIRECTORY,
                                                       new_directory_name)
                    os.mkdir(self.user_repo_path)
                    os.chdir(self.user_repo_path)
                else:
                    self.user_repo_path = os.path.join(CURRENT_WORKING_DIRECTORY, path)
                print_info("cloning the user provided url")
                git.Git(os.getcwd()).clone(self.imp_url)
                if match_flag9:
                    os.system("mv {}/ {}".format(existing_name, mod_path))

                if not self.user_repo_path.endswith(path):
                    self.user_repo_path = os.path.join(self.user_repo_path, path)

                verify = Verify_Import_Statements(self.user_repo_path)
                verify.verify_import_statements(self.user_repo_path)
                if user_dir_path_flag:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))
                elif self.imp_output_dir:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))
                else:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))
            else:
                bool_found = self.check_packages("pip")
                if not bool_found:
                    print_info("pip is not installed ")
                else:
                    print_info("pip is installed proceeding further !!!")
                git_status = self.check_git_status()
                if git_status:
                    print_info("Git is available proceeding further ")
                else:
                    print_info("Git is not installed on the system. "
                          "Please install git and restart this installation.")
                self.install_depen("virtualenv", "virtualenv")
                virt_act_status = self.activate_virtualenv()
                if virt_act_status:
                    print_info("successfully activated virtualenv")
                else:
                    print_info("Not able to activate the virtual env")
                dep_install_status = self.install_depen("GitPython", "git")
                if dep_install_status:
                    print_info("Successfully installed package {}".format("GitPython"))
                else:
                    print_info("Not able to install the package {}".format("GitPython"))
                import git
                path = self.imp_url.split("/")[-1].split(".")[0]
                user_dir_path_flag = False

                if self.imp_output_dir:
                    self.user_repo_path = self.imp_output_dir
                    if os.path.exists(self.user_repo_path):
                        os.chdir(self.user_repo_path)
                    else:
                        print_info("the provided path {} is not found ".format(self.user_repo_path))
                        sys.exit()
                elif os.path.exists(os.path.join(CURRENT_WORKING_DIRECTORY, path)):
                    user_dir_path_flag = True
                    import time
                    timestamp = time.time()
                    new_directory_name = "{}_{}".format(path, int(timestamp))
                    self.user_repo_path = os.path.join(CURRENT_WORKING_DIRECTORY,
                                                       new_directory_name)
                    os.mkdir(self.user_repo_path)
                    os.chdir(self.user_repo_path)
                    print_info("Found the same name {} directory in current working directory , hence "
                          "creating new directory {}".format(path, new_directory_name))
                else:
                    self.user_repo_path = os.path.join(CURRENT_WORKING_DIRECTORY, path)
                print_info("cloning the user provided url")
                git.Git(os.getcwd()).clone(self.imp_url)
                verify = Verify_Import_Statements(self.user_repo_path)
                verify.verify_import_statements(self.user_repo_path)
                if user_dir_path_flag:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))
                elif self.imp_output_dir:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))
                else:
                    print_info("The changes will be available in this {} folder".format(
                        self.user_repo_path))

if sys.version_info < (3, 4):
    print_info("This script doesn't support Python version lower than 3.4")
    sys.exit(0)

if (imp_url and imp_output_dir) or (user_repo_path and imp_output_dir) or (imp_url) or\
        (user_repo_path):
    print_info("Performing operation on Verify Import Statements")

    START_HERE = pre_requirements(warrior_repo, keyword_repos, add_repo_output, imp_url,
                                  user_repo_path, imp_output_dir, add_repo_war_repos_path,
                                  add_repo_kw_repos_path)

    START_HERE.verify_import_statements_starts()

elif (warrior_repo and keyword_repos and add_repo_output) or (warrior_repo and keyword_repos):
    print_info("Performing operation on Add Repo in StepSection")

    START_HERE = pre_requirements(str(args.add_repo_warrior_url), str(args.add_repo_keyword_url),
                                  add_repo_output, imp_url, user_repo_path, imp_output_dir,
                                  add_repo_war_repos_path, add_repo_kw_repos_path)
    START_HERE.add_repo_in_step_starts()

elif (add_repo_war_repos_path and add_repo_kw_repos_path and add_repo_output) or \
        (add_repo_war_repos_path and add_repo_kw_repos_path):

    START_HERE = pre_requirements(warrior_repo, keyword_repos, add_repo_output, imp_url,
                                  user_repo_path, imp_output_dir, str(args.add_repo_war_repos_path),
                                  str(args.add_repo_kw_repos_path))
    START_HERE.add_repo_in_step_repos()
else:
    print_info("To run this script Arguments Requried")
    print_info('To know the syntax of argument to be use this command "python warrior_py3_migration_tools --help"')
    sys.exit()