#!/usr/bin/env python
import argparse
import os
import re
import sys
from random import randint
from zipfile import ZipFile
from tempfile import NamedTemporaryFile
import base64
from xml.etree import ElementTree
import requests
def publish(parentid,pubfile,pubattach=None):
    """ Given a RAMADDA parent_id and list of case_names this function
    publishes to ramadda with user credentials taken from environment variables
    RAMADDA_USER and RAMADDA_PASSWORD

    TODO: lot of redundant code in for loops checking if files exist
    TODO: do it with xml not by strings
    TODO: currently creating a folder is not possible, user has to supply a folder
    but can be fixed by adding an entry to xml_string group, but needs to handle
    user running script  multiple times.
    """
    assert isinstance(parentid, str), "publish_url must be a string"
    try:
        postadd = os.environ['RAMADDA']
    except KeyError:
        postadd = "https://weather.rsmas.miami.edu/repository/entry/xmlcreate"

    xml_string = ''  # '<entries>'  # add group here later
    filetype=pubfile.split('.')[-1]
    if filetype=='zidv' or filetype=='xidv':
       ramadda_filetype="type_idv_bundle"
    else:
       print('unknown upload file type')
       sys.exit()
    if pubattach:
       pubtype=pubattach.split('.')[-1]
       #print pubtype.lower()=='png'
       if not pubtype.lower() in ('gif','jpeg','jpg','png'):
          print('unknown attachment type')
          sys.exit()
    if pubfile:
        pubfile_name = os.path.split(pubfile)[-1]
        xml_string += '<entry name="{0}" file="{0}" ' \
                      'type="type_idv_bundle">'.format(pubfile_name)
        if pubattach:
             pubattach_name = os.path.split(pubattach)[-1]
             xml_string += '<metadata inherited="false" type="content.thumbnail">'
             xml_string += '<attr fileid="{0}" index="1">'.format(pubattach_name)
             encoded_case_str = base64.b64encode(pubattach).decode('ascii')
             xml_string += '<![CDATA[{0}]]>'.format(encoded_case_str)
             xml_string += '</attr>'
             xml_string += '</metadata>'
        xml_string += '</entry>'
    else:
       print('ERROR: upload file doesnt exist?')
       sys.exit(1)
    # xml_string += '</entries>'
    #print xml_string
    try:
        user = os.environ['RAMADDA_USER']
        password = os.environ['RAMADDA_PASSWORD']
    except KeyError as err:
        print('Publish error {0}'.format(err))

    with NamedTemporaryFile(suffix=".zip",delete=False) as tmpzip:
        with ZipFile(tmpzip.name, 'w') as zipfile:
            zipfile.writestr('entries.xml', xml_string)
            pubfile_name = os.path.split(pubfile)[-1]
            zipfile.write(pubfile)
            if pubattach:
               pubattach_name = os.path.split(pubfile)[-1]
               zipfile.write(pubattach)
            files = {"file": open(tmpzip.name, "rb")}
            resp = requests.post(postadd, files=files,
                                 data={'group': parentid,
                                       'auth.user': user, 'auth.password': password,
                                       'response': 'xml'})
    publish_attrib = ElementTree.fromstring(resp.text).attrib
    if publish_attrib['code'] == 'ok':
        print('Published case {0} '.format(pubfile))
    else:
        print('Publish case {0} failed with {1}'.format(pubfile, publish_attrib['code']))
    return None

def check_file(f):
    """
    'Type' for argparse - checks that file exists but does not open.
    """
    if not os.path.exists(f):
        raise argparse.ArgumentTypeError("{0} does not exist".format(f))
    return f
if __name__ == '__main__':
    """TODO : 1) make file and entryid also optional args
              2) support multiple filetypes
              3) support creating directory 
              4) cleanup publish api"""
    parser = argparse.ArgumentParser(description='Script to publish files to a RAMADDA server',
                                     epilog='Simplest use case:ramadda_publish publish_file publish_at_entry_id')
    parser.add_argument('publish_file',type=check_file,
                        help='Publish  a file to a RAMADDA server;'
                             'Currently only IDV bundles are supported as files.')
    parser.add_argument('entryid',
                        help='Parent entryid string on a RAMADDA server.'
                             'It should contain just the string NOT entire url path.'
                             'NOTE: RAMADDA_USER needs to have permissions for publishing the file'
                             ' on the RAMADDA server')
    parser.add_argument('-a','--attachment',type=check_file,
                        help='Publish this file as an attachment.'
                             'Currently only image files are supported')
    parser.add_argument('-ramadda', '--ramadda',
                        help='The RAMADDA server.'
                             'By default RAMADDA environment variable is used, if it is absent'
                             'the url https://weather.rsmas.miami.edu/repository/entry/xmlcreate '
                             'is used.')
    parser.add_argument('-user', '--user',
                        help='User for RAMADDA, by default, if exists, the environment variable' 
                             'RAMADDA_USER is used as a user.')
    parser.add_argument('-password', '--password',
                        help='Password for -user or RAMADDA_USER, by default, if exists,' 
                             'the environment variable RAMADDA_PASSWORD is used as a user password.')

    
    pargs = parser.parse_args()
#    sys.exit()
#    if len(sys.argv)==3:
#       if not sys.argv[1].startswith('-'):
#           publish(sys.argv[2],sys.argv[1])
#    elif len(sys.argv)==4: 
#       if not sys.argv[1].startswith('-'):
#           publish(sys.argv[3],sys.argv[1],sys.argv[2])
#    else:
    if pargs.ramadda:
        os.environ['RAMADDA']=pargs.ramadda
    if pargs.user:
        os.environ['RAMADDA_USER']=pargs.user
    if pargs.user:
        os.environ['RAMADDA_PASSWORD']=pargs.password
    attachment=pargs.attachment if pargs.attachment else None
    publish(pargs.entryid,pargs.publish_file,attachment)
