import os, sys
from os.path import isfile, isdir, join
import json
import requests

def msg(s): print (s)
def dashes(): msg(40*'-')
def msgt(s): dashes(); msg(s); dashes()
def msgx(s): msgt('Error.  Exiting'); msg(s); dashes(); sys.exit(0)


"""
## FILL IN THE FOLLOWING MANDATORY VARIABLES
REPO_NAME = 'github repository name'
REPO_OWNER_NAME = 'github repository owner name'

GITHUB_AUTH_USERNAME = 'github-username'
# For A GitHub personal access token: https://github.com/settings/applications#personal-access-tokens
GITHUB_PERSONAL_API_TOKEN_OR_PASSWORD = ''  
## end: neeeded MANDATORY VARIABLES

"""
class GithubLabelMaker:
    
    GITHUB_SPEC_ATTRIBUTE_NAMES = [ 'REPO_NAME', 'REPO_OWNER_NAME', 'GITHUB_AUTH_USERNAME', 'GITHUB_PERSONAL_API_TOKEN_OR_PASSWORD' ]
    
    def __init__(self, github_specs_filename, label_specs_filename):

        assert isfile(github_specs_filename), "The github_specs file was not found: %s" % github_specs_filename
        assert isfile(label_specs_filename), "The label specs file was not found: %s" % label_specs_filename
        
        self.load_github_specs_from_json_file(github_specs_filename)
        self.add_labels(label_specs_filename)
    
    
    def load_github_specs_from_json_file(self, github_specs_fname):
        """
        Create and load class attributes for each of the GITHUB_SPEC_ATTRIBUTE_NAMES

        e.g. self.REPO_NAME = 'something in JSON file'
        """
        assert isfile(github_specs_fname), "The github_specs file was not found: %s" % github_specs_filename

        try:
            d = json.loads(open(github_specs_fname, 'rU').read())
        except:
            msgx('Could not parse JSON in file: %s' % github_specs_fname)
        
        for attr in self.GITHUB_SPEC_ATTRIBUTE_NAMES:
            if not d.has_key(attr):
                msgx('Value not found for "%s".  The github specs file "%s" must have a "%s"' % (attr, github_specs_fname, attr ))
            #print ('loaded: %s->%s' % (attr, self.__dict__[attr]))
            self.__dict__[attr] = d[attr]
        
        
    def get_github_auth(self):
        return (self.GITHUB_AUTH_USERNAME, self.GITHUB_PERSONAL_API_TOKEN_OR_PASSWORD)

    def get_label_url(self, label_name):
        assert label_name is not None, "Label name cannot be None"
        
        return 'https://api.github.com/repos/%s/%s/labels/%s' % (self.REPO_OWNER_NAME, self.REPO_NAME, label_name )       
        
    def get_create_label_url(self):
        return 'https://api.github.com/repos/%s/%s/labels' % (self.REPO_OWNER_NAME, self.REPO_NAME )
    
    
    def add_labels(self, label_fname):
        assert isfile(label_fname), 'File not found [%s]' % label_fname
          
        flines = open(label_fname, 'rU').readlines()
    
        # strip lines and skip comments
        #
        flines = [x.strip() for x in flines if len(x.strip()) > 0 and not x.strip()[:1]=='#']
    
        # split each line into a tuple: (label_name, label_color)
        #
        info_lines = [x.split('|') for x in flines if len(x.split('|'))==2]
    
        # Create each label--or update the color if label name exists and color is different
        #
        cnt = 0
        for label_info in info_lines:
            run_update_color = False
            
            if not len(label_info) == 2:    
                continue    # shouldn't happen
            
            
            label_info = [x.strip() for x in label_info]    # strip each value
            label_name, label_color = label_info    # split the tuple into 2 vals
            label_color = label_color.lower()   # color in lowercase
            
        
            if len(label_name) == 0:
                msgx('The label name is blank!\nFrom line with "%s"' % ('|'.join(label_info)))
            
            if not len(label_color)==6:
                msgx('This label color should be 6 characters: "%s"\nFrom line with "%s"' % (label_color, 
                '|'.join(label_info)))
        
            cnt += 1
            msgt('(%s) Create label [%s] with color [%s]' % (cnt, label_name, label_color))
                

            github_label_url = self.get_label_url(label_name)   
            msg('github_label_url: %s' % github_label_url)    
            
            r = requests.get(github_label_url, auth=self.get_github_auth())

            if r.status_code == 200:
                label_json = json.loads(r.text)
                if label_json.get('color', '').lower() == label_color:
                    msg('Label already exists with same color!')
                    continue
                else:
                    msg('Label exists BUT different color...')
                    run_update_color = True
        
            data = dict(name=label_name, color=label_color)
            if run_update_color:
                r = requests.patch(get_label_url, data=json.dumps(data), auth=self.get_github_auth())
            else:
                #create_label_url = 'https://api.github.com/repos/%s/%s/labels' % (REPO_OWNER_NAME, REPO_NAME )
                r = requests.post(self.get_create_label_url(), data=json.dumps(data), auth=self.get_github_auth())
        
        
            if r.status_code == 200:
                msg('Label color updated!')
            elif r.status_code == 201:
                msg('Label created!')
            else:
                msg('Label failed!')
            msg(r.text)



def show_instructions():
    dashes()
    msg("""Please run this script from the command line as follows:
    
     >python label_update.py [github_specs.json] [label input filename]
     example: >python label_update.py github_specs_template.json label_input_dataverse-org.txt

-----------------------------
-- Label Input file --
-----------------------------

Each line of the label input file includes:
    (1) label name
    (2) label color (hex) 

This info is separated by a '|' delimiter.

    Format:  "Label Name|Hex Color"

Notes:
    - The file has no header line. 
    - Blank lines and comment lines ('#') are ignored
    - Each line is trimmed
    - Label names and colors are trimmed
    
Example file contents:

Priority: Critical|ff9900
Priority: High|e11d21
# Priority: Medium|cc6666  -- this line is ignored
Status: Design|66ff66
Status: Dev|66cc66
Status: QA|336633


    """)

if __name__=='__main__':
    if len(sys.argv) == 3:
        GithubLabelMaker(sys.argv[1], sys.argv[2])
        #add_labels(sys.argv[1])
    else:
        show_instructions()