#!/usr/bin/python
from bottle import Bottle, run, template, static_file, error, redirect, post, request
import yaml
import glob
import re
import time
import random
import string
import os
import shutil
import subprocess

app = Bottle()

APP_ROOT = "/home/beieli"

# Read Configuration from YAML-File
with open("%s/bin/beielimon-config.yaml" % (APP_ROOT), 'r') as stream:
    try:
        config_data = yaml.load(stream)
    except yaml.YAMLError as exc:
        print(exc)

def GetLastValues(scale_uuid):
    last_weight = ""
    last_weight_timestamp = ""
    last_swarmalarm = ""
    files = glob.glob("%s/data/weight-%s-????????.log" % (APP_ROOT,scale_uuid))
    if len(files) > 0:
        with open(sorted(files)[-1], "r") as f:
            for line in f: pass
            result =  line

        # Beispiel: 2017-11-07 08:23,0
        m = re.match("(\d{4})-(\d{2})-(\d{2}) (\d\d:\d\d),(\d+)", result)
        if m:
            last_weight = "%sg" % (m.group(5))
            last_weight_timestamp = "%s.%s.%s %s" % (m.group(3),m.group(2),m.group(1),m.group(4))
        else:
             last_weight = "Fehler beim Parsen: %s" % (result)
             last_weight_timestamp = ""

    else:
       last_weight = "Keine Messwerte"
       last_weight_timestamp = "N/A"

    files = glob.glob("%s/data/swarmalarm-%s-????????.log" % (APP_ROOT,scale_uuid))
    if len(files) > 0:
        with open(sorted(files)[-1], "r") as f:
            for line in f: pass
            result =  line

        # Beispiel: 2017-11-07 08:23
        m = re.match("(\d{4})-(\d{2})-(\d{2}) (\d\d:\d\d)", result)
        if m:
            last_swarmalarm = "%s.%s.%s %s" % (m.group(3),m.group(2),m.group(1),m.group(4))
        else:
             last_swarmalarm = "Fehler beim Parsen: %s" % (result)

    else:
       last_swarmalarm = "keiner"

    return [last_weight, last_weight_timestamp, last_swarmalarm ]

def RefreshData():
    scales = config_data['scales']
    hash_scales = {}
    for s in config_data['scales']:
       uuid = s['scale_uuid']
       (last_weight, last_weight_timestamp, last_swarmalarm) = GetLastValues(uuid)
       hash_scales[uuid] = {}
       hash_scales[uuid]['alias'] = s['alias']
       hash_scales[uuid]['last_weight'] = last_weight
       hash_scales[uuid]['last_weight_timestamp'] = last_weight_timestamp
       hash_scales[uuid]['last_swarmalarm'] = last_swarmalarm
    return hash_scales

def CreateDatafile(scale_uuid,infotime):
    mycsvdir = "%s/web-csv" % (APP_ROOT)
    my_pattern = '%s%s' % (infotime,'?' * (8 - len(infotime)))
    files = glob.glob("%s/data/weight-%s-%s.log" % (APP_ROOT,scale_uuid,my_pattern))
    filename = "%s/%s-%s.csv" % (mycsvdir,scale_uuid,infotime)
    with open(filename, 'w') as file:
        for ifile in sorted(files):
            if infotime in ifile:
                with_data = True
                with open(ifile, 'r') as ifile:
                    for line in ifile:
                        file.write(line)
    files = glob.glob("%s/data/temp-%s-%s.log" % (APP_ROOT,scale_uuid,my_pattern))
    filename = "%s/temp-%s-%s.csv" % (mycsvdir,scale_uuid,infotime)
    with open(filename, 'w') as file:
        for ifile in sorted(files):
            if infotime in ifile:
                with_data = True
                with open(ifile, 'r') as ifile:
                    for line in ifile:
                        file.write(line)
    files = glob.glob("%s/data/humidity-%s-%s.log" % (APP_ROOT,scale_uuid,my_pattern))
    filename = "%s/humidity-%s-%s.csv" % (mycsvdir,scale_uuid,infotime)
    with open(filename, 'w') as file:
        for ifile in sorted(files):
            if infotime in ifile:
                with_data = True
                with open(ifile, 'r') as ifile:
                    for line in ifile:
                        file.write(line)
    files = glob.glob("%s/data/accu-%s-%s.log" % (APP_ROOT,scale_uuid,my_pattern))
    filename = "%s/accu-%s-%s.csv" % (mycsvdir,scale_uuid,infotime)
    with open(filename, 'w') as file:
        for ifile in sorted(files):
            if infotime in ifile:
                with_data = True
                with open(ifile, 'r') as ifile:
                    for line in ifile:
                        file.write(line)

def GetInfoText():
    with open('%s/bin/beielimon-config.yaml' % (APP_ROOT), 'r') as f:
        config_file_lines = f.read()

    # Wir maskieren das Passwort
    config_file_lines = re.sub(r"mailpwd:.*\n", "mailpwd: MASKED\n", config_file_lines)

    commands_output = ""
    for comm_arr in [ ['uptime','--pretty'],
                      ['date'],
                      ['uname', '-a'],
                      ['df','-h','/boot','/root'],
                      ['free','-m'],
                      ['ip','a'] ]:
        commands_output = "%s\n# %s\n%s" % (commands_output,' '.join(comm_arr),subprocess.check_output(comm_arr))
    
    res = """Konfigurationsfile:<br />

<pre>%s</pre>

Diverse Befehle: <pre>%s</pre>

""" % (config_file_lines, commands_output)

    return res


def is_valid_yaml(yaml_string):
    res = True
    try:
        data_parsed = yaml.safe_load(yaml_string)
    except yaml.YAMLError:
        res = False

    return res

@app.route('/')
def index():
    hash_scales = RefreshData()
    data = { 
             'scales': hash_scales,
             'infotime': time.strftime("%Y", time.localtime()),
             'beielipi_mobile_number': config_data['beielipi_mobile_number'],
             'infotext': GetInfoText()
           }

    return template('%s/web-root/index.tpl' % (APP_ROOT), data)

@app.get('/upload_config')
def upload_config():
    my_message = request.GET.get('message', '').strip()
    my_level = request.GET.get('level', '').strip()
    data = { 
             'message': my_message,
             'level': my_level
           }

    return template('%s/web-root/upload_config.tpl' % (APP_ROOT), data)

@app.post('/upload_config')
def do_upload_config():
    config_yaml = request.forms.get('config_yaml')
    if is_valid_yaml(config_yaml):
        # Wir machen noch ein Backup vor dem Ueberschreiben
        date_format_string = "+%Y%m%d-%H%M%S"
        os.system('cp %s/bin/beielimon-config.yaml %s/config-backups/beielimon-config.yaml.$(date %s)' % (APP_ROOT,APP_ROOT,date_format_string)) 
        with open('%s/bin/beielimon-config.yaml' % (APP_ROOT), 'w') as file:
            file.write(string.replace(config_yaml,'\r',''))
        redirect("/upload_config?message=Konfiguration%20erfolgreich%20ersetzt.%20Bitte%20BeieliPi%20rebooten%20mit%20http%3A%2F%2Fbeielipi.local%2Freboot_beielipi&level=success")
    else:
        redirect("/upload_config?message=Fehler%20mit%20YAML-Syntax&level=danger")

@app.route('/reboot_beielipi')
def reboot_beielipi():
    os.system('/sbin/init 6') 

@app.route('/static/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='%s/web-root/static' % (APP_ROOT))

@app.route('/data/<filepath:path>')
def server_static(filepath):
    return static_file(filepath, root='%s/web-csv' % (APP_ROOT))

@app.route('/scale/<scale>/<infotime>')
def scale_data(scale,infotime):
    scale_uuid = ''
    scale_alias = ''
    interface_type = ''
    for s in config_data['scales']:
        if s['alias'].replace(' ','_') == scale:
            scale_uuid = s['scale_uuid']
            scale_alias = s['alias']
            interface_type = s['interface_type']

    CreateDatafile(scale_uuid, infotime)
    data = { 
             'scale_uuid': scale_uuid,
             'scale_alias': scale_alias,
             'interface_type': interface_type,
             'infotime': infotime
           }

    return template('%s/web-root/scale.tpl' % (APP_ROOT), data)

@app.route('/download/<infotime>')
def download(infotime):
    mypid = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(7))
    mycsvdir = "%s/tmp/%s/csv" % (APP_ROOT,mypid)
    if not os.path.exists(mycsvdir):
        os.makedirs(mycsvdir)
    myzipdir = "%s/tmp/%s/zip" % (APP_ROOT,mypid)
    if not os.path.exists(myzipdir):
        os.makedirs(myzipdir)
    my_pattern = '%s%s' % (infotime,'?' * (8 - len(infotime)))
    files = glob.glob("%s/data/weight-*-%s.log" % (APP_ROOT,my_pattern))
    for s in config_data['scales']:
        filename = "%s/%s-%s.csv" % (mycsvdir,s['alias'].replace(' ','_'),infotime)
        with open(filename, 'a') as file:
            for ifile in sorted(files):
                if (s['scale_uuid'] in ifile) and (infotime in ifile):
                    with open(ifile, 'r') as ifile:
                        for line in ifile:
                            m = re.match("(\d{4})-(\d{2})-(\d{2}) (\d\d:\d\d),(\d+)", line)
                            if m:
                                file.write("%s.%s.%s %s,%s\n" % (m.group(3),m.group(2),m.group(1),m.group(4),m.group(5)))
                            else:
                                file.write("Fehler beim Parsen: %s" % (line))

    zipfile = "%s/%s" % (myzipdir,infotime)
    shutil.make_archive(zipfile, 'zip', mycsvdir)
    zipfilename = "%s.zip" % (infotime)
    return static_file(zipfilename, root=myzipdir, mimetype='application/zip',download=zipfilename)

@app.error(404)
def error404(error):
    return index()

run(app, host='0.0.0.0', port=80)
