#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# $Id$
#
"""Create environment variable symlinks.
"""
from __future__ import absolute_import, division, print_function, unicode_literals
#
# Top-level definitions.
#
__author__ = 'Benjamin Weaver <benjamin.weaver@nyu.edu>'
__version__ = '$Revision$'.split(': ')[1].split()[0]
__all__ = [ ]
__docformat__ = 'restructuredtext en'
#
# Modules
#
import argparse
from collections import OrderedDict
import ConfigParser
import glob
import os
import os.path
import sys
import time
#
# parse_cfg()
#
def parse_cfg(cfg,root):
    """Parse a tree configuration file.

    Parameters
    ----------
    cfg : ConfigParser.ConfigParser
        A ``ConfigParser`` object.
    root : str
        The value of ``$SAS_BASE_DIR``.

    Returns
    -------
    env : collections.OrderedDict
        A mapping containing all the configuration file data
    """
    env = OrderedDict()
    replace = '@FILESYSTEM@'
    env['default'] = cfg.defaults()
    if env['default']['FILESYSTEM'] == replace:
        env['default']['FILESYSTEM'] = root
    # env['default']['install'] = os.path.dirname(os.path.dirname(os.getenv('INSTALL_DIR')))
    env['default']['current'] = env['default']['current'] == 'True'
    for sec in cfg.sections():
        env[sec] = OrderedDict()
        for opt in cfg.options(sec):
            if opt in env['default']:
                continue
            val = cfg.get(sec,opt)
            if val.find(replace) == 0:
                val = val.replace(replace,root)
            env[sec][opt] = val
    return env
#
#
#
def make_link(src,link,options):
    """Encapsulate link creation
    """
    debug = options.test or options.verbose
    if debug:
        print("{0} -> {1}".format(link,src))
    if not options.test:
        if os.path.islink(link):
            os.remove(link)
        os.symlink(src,link)
    return
#
# Main function
#
def main():
    """Program to run if called as an executable."""
    #
    # Get options
    #
    parser = argparse.ArgumentParser(description=__doc__,prog=os.path.basename(sys.argv[0]))
    parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
        help='Print extra information.')
    parser.add_argument('-f', '--force', action='store_true', dest='force',
        help='Force the creation of some symlinks.')
    parser.add_argument('-t', '--test', action='store_true', dest='test',
        help='Only show what would be done (implies --verbose).')
    parser.add_argument('-m', '--mirror', action='store_true', dest='mirror',
        help='SAM version.')
    parser.add_argument('-o', '--only', action='store', dest='only',
        default='ALL', metavar='TREE',
        help='Create links for only TREE.')
    parser.add_argument('-r', '--root', action='store', dest='root',
        default=os.path.dirname(os.getenv('SAS_BASE_DIR')),
        help='Override the value of $SAS_BASE_DIR.',metavar='DIR')
    options = parser.parse_args()
    debug = options.test or options.verbose
    #
    # Find the data directory
    #
    datadir = os.path.join(os.getenv('TREE_DIR'),'data')
    if not os.path.exists(datadir):
        datadir = os.path.join('..','data')
        if not os.path.exists(datadir):
            print("Could not find a data directory!")
            return 1
    #
    # Set up index file
    #
    header = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta name="viewport" content="width=device-width"/><meta http-equiv="content-type" content="text/html; charset=utf-8"/><style type="text/css">body,html {background:#fff;font-family:"Bitstream Vera Sans","Lucida Grande","Lucida Sans Unicode",Lucidux,Verdana,Lucida,sans-serif;}tr:nth-child(even) {background:#f4f4f4;}th,td {padding:0.1em 0.5em;}th {text-align:left;font-weight:bold;background:#eee;border-bottom:1px solid #aaa;}#list {border:1px solid #aaa;width:100%%;}a {color:#a33;}a:hover {color:#e33;}</style>
<link rel="stylesheet" href="%(url)s/css/sas.css" type="text/css"/>
<title>Index of /sas/%(name)s/env/</title>
</head><body><h1>Index of /sas/%(name)s/env/</h1>
"""

    table_header = """<table id="list" cellpadding="0.1em" cellspacing="0">
<colgroup><col width="55%"/><col width="20%"/><col width="25%"/></colgroup>
<thead>
    <tr><th><a href="?C=N&O=A">File Name</a>&nbsp;<a href="?C=N&O=D">&nbsp;&darr;&nbsp;</a></th><th><a href="?C=S&O=A">File Size</a>&nbsp;<a href="?C=S&O=D">&nbsp;&darr;&nbsp;</a></th><th><a href="?C=M&O=A">Date</a>&nbsp;<a href="?C=M&O=D">&nbsp;&darr;&nbsp;</a></th></tr>
</thead><tbody>
    <tr><td><a href="../">Parent directory/</a></td><td>-</td><td>-</td></tr>
"""
    table_footer = """</tbody></table>
"""
    footer = """<h3><a href='%(url)s/sas/'>%(location)s</a></h3>
<p>This directory contains links to the contents of
environment variables defined by the tree product, version %(name)s.
To examine the <em>types</em> of files contained in each environment variable
directory, visit <a href="/datamodel/files/">the datamodel.</a></p>
</body></html>
"""

    #
    # Read the configuration files
    #
    for cfgfile in glob.glob(os.path.join(datadir,'*.cfg')):
        cfg = ConfigParser.SafeConfigParser()
        cfg.optionxform = str
        cfg.read(cfgfile)
        env = parse_cfg(cfg,options.root)
        if options.only != 'ALL' and env['default']['name'] != options.only:
            continue
        # if debug:
        #     print(env)
        env['default']['url'] = "https://data.mirror.sdss.org" if options.mirror else "https://data.sdss.org"
        env['default']['location'] = "SDSS-IV Science Archive Mirror (SAM)" if options.mirror else "SDSS-IV Science Archive Server (SAS)"
        if os.path.exists(env['general']['SAS_ROOT']):
            if debug:
                print("Found {0}.".format(env['general']['SAS_ROOT']))
            envdir = os.path.join(env['general']['SAS_ROOT'],'env')
            if os.path.exists(envdir):
                if not os.access(envdir,os.W_OK):
                    print("{0} does not appear to be writeable, skipping...".format(envdir))
                    continue
            else:
                if debug:
                    print("Creating {0}.".format(envdir))
                if not options.test:
                    os.mkdir(envdir)
            index = header % env['default']
            index += table_header
            svars = list()
            for section in env:
                if section == 'default':
                    continue
                keys = list(env[section].keys())
                svars += zip(keys,[section]*len(keys))
            if debug:
                print(svars)
            svars.sort(key=lambda x: x[0])
            if debug:
                print(svars)
            for var in svars:
                if var[0].find('_ROOT') > 0:
                    continue
                src = env[var[1]][var[0]]
                link = os.path.join(envdir,var[0])
                try:
                    stattime = time.strftime('%d-%b-%Y %H:%M',time.localtime(os.stat(src).st_mtime))
                except OSError:
                    print("{0} does not appear to exist, skipping...".format(src))
                    if os.path.islink(link):
                        os.remove(link)
                    continue
                if var[1] == 'general' and var[0] in ('SAS_BASE_DIR'):
                    print("Skipping %r for %r" % var)
                elif var[1] == 'general' and var[0] in ('CAS_LOAD','STAGING_DATA'):
                    #
                    # For this section only, install links only if their
                    # targets exist. The --force option overrides this.
                    #
                    if options.force or os.path.exists(src):
                        make_link(src,link,options)
                        index += '    <tr><td><a href="{0}/">{0}/</a></td><td>-</td><td>{1}</td></tr>\n'.format(var[0],stattime)
                        print("Forcing / Processing %r for %r" % var)
                    else: print("Skipping (without force) %r for %r" % var)
                else:
                    print("Processing %r for %r" % var)
                    make_link(src,link,options)
                    index += '    <tr><td><a href="{0}/">{0}/</a></td><td>-</td><td>{1}</td></tr>\n'.format(var[0],stattime)
            index += table_footer
            index += footer % env['default']
            indexfile = os.path.join(envdir,'index.html')
            if debug:
                print("Creating {0}.".format(indexfile))
                print(index)
            if not options.test:
                with open(indexfile,'w') as f:
                    f.write(index)
        else:
            print("{0} doesn't exist, skipping env link creation.".format(env['general']['SAS_ROOT']))
    return 0
#
#
#
if __name__ == '__main__':
    sys.exit(main())
