import os
import re
import sys
import string
import requests
from itertools import cycle
from lxml.html import fromstring
from clint.textui import colored, puts

class GithubSectory():
    """ docstring for GithubSectory : Python script to download Github Project Subdirectory! """

    def __init__(self):
        self.link = ""
        self.arg = sys.argv
        self.gh = "https://github.com/"
        self.proxies = cycle(self.get_proxies())
        self.ghapi = "https://api.github.com/repos/"

    def clear(self):
        """for removing the clutter from the screen when necessary"""

        os.system('cls' if os.name == 'nt' else 'clear')

    def get_proxies(self):
        url = 'https://free-proxy-list.net/'
        response = requests.get(url)
        parser = fromstring(response.text)
        proxies = set()
        for i in parser.xpath('//tbody/tr')[:10]:
            if i.xpath('.//td[7][contains(text(),"yes")]'):
                proxy = ":".join([i.xpath('.//td[1]/text()')
                                  [0], i.xpath('.//td[2]/text()')[0]])
                proxies.add(proxy)
        return proxies

    def getSysArguments(self):
        """ Lets see what kind of input user has given to us """

        try:
            self.link = sys.argv[1]
        except Exception as e:
            puts(colored.red("Error : Not argument. Truncating process!"))
            sys.exit(0)

        if not re.search(r'github.com', self.link):

            puts(colored.magenta("[ Validating Input Parameters ]"))

            for index, arg in enumerate(self.arg):
                if arg == "-r":
                    self.repo = self.arg[index+1]
                if arg == "-d":
                    self.dir = self.arg[index+1]
                if arg == "-b":
                    self.branch = self.arg[index+1]

            try:
                self.link = self.ghapi + sys.argv[1]
            except Exception as e:
                puts(colored.red(
                    "Error : User/Organisation not mentioned. Truncating process!"))
                sys.exit(0)

            try:
                self.link = self.link + "/" + self.repo
            except Exception as e:
                puts(colored.red("Error : Repository not mentioned. Truncating process!"))
                sys.exit(0)

            try:
                self.link = self.link + "/contents/" + self.dir
                try:
                    self.link = self.link + "?ref=" + self.branch
                    self.downloadMe(self.link)
                except AttributeError:
                    self.downloadMe(self.link)
            except AttributeError:
                self.link = self.gh + sys.argv[1] + "/" + self.repo + ".git"
                self.downloadMe(self.link)

        else:
            puts(colored.magenta("[ Validating Input URL ]"))
            if len(self.link.split("/")) < 7:
                puts(colored.green(
                    "Normal Link, use git commands to clone repository!"))
            else:
                self.link = self.link.replace(self.gh, self.ghapi)
                self.link = self.link.replace('tree', 'contents')
                self.linkList = self.link.split("/")
                self.repo = self.dir = self.linkList[8]
                self.link = self.link.replace(self.linkList[7]+"/", '')
                self.link = self.link + "/?ref=" + self.linkList[7]
                self.downloadMe(self.link)

    def downloadMe(self, parameter):
        """ Method to download file, link is passed via parameter """

        puts(colored.yellow("[ Getting folder content ]"))
        proxy = next(self.proxies)
        puts(proxy)
        self.downloadLink = parameter
        puts(self.downloadLink)
        try:
            self.parsed = requests.get(self.downloadLink).json()
        except requests.HTTPError as err:
            if err.code == 404:
                puts(colored.red("[ Invalid URL! Maybe private repo ]"))
                sys.exit(0)
            else:
                puts(err)
                sys.exit(0)

        if not os.path.exists(self.dir):
            os.makedirs(self.dir)
        self.tempPath = os.path.join(os.getcwd(), self.dir)
        puts(colored.green("[ Downloading all required files ]"))
        self.workingRecursively(self.tempPath, self.parsed)
        puts(colored.green("[ Finished ]"))

    def workingRecursively(self, filepath, filedata):
        """ Get the List of all filenames and link of required subdirectory """

        proxy = next(self.proxies)

        for file in filedata:
            if file['type'] == "file":
                fileCreate = open(os.path.join(filepath, file['name']), 'a+')
                fileCreate.write(requests.get(file['download_url']).text)
                fileCreate.close()
            else:
                changedPath = os.path.join(filepath, file['name'])
                if not os.path.exists(changedPath):
                    os.makedirs(changedPath)
                newFileData = requests.get(file['url']).json()
                self.workingRecursively(changedPath, newFileData)


if __name__ == '__main__':
    GithubSectory().getSysArguments()
