#!/usr/bin/python3
## -*- coding: utf-8 -*-
#
#
# Copyright (C) 2011, Thomas Mashos, for Mythbuntu
#
#
# Mythbuntu-bare is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this application; if not, write to the Free Software Foundation, Inc., 51
# Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
##################################################################################

import configparser
import os
import shutil
import hashlib
import platform
import logging

CONFIGFILENAME = "mythbuntu-bare-client.conf"
CONFIGPATH = "/var/lib/mythtv/bare-client/"

TMPCONFIGFILENAME="mythbuntu-bare.conf"

CONFIGFILE = CONFIGPATH+CONFIGFILENAME
TMPCONFIGFILE = "/tmp/"+TMPCONFIGFILENAME

logger = logging.getLogger('mythbuntu-bare')
hdlr = logging.FileHandler('/var/log/mythbuntu-bare-client.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr) 
logger.setLevel(logging.WARNING)

ACTOR="<mythbareupdate> "

class Update():

    def update_job(self, ServerIP=None, ServerPort=None):
        logger.info(ACTOR+'Update job started')
        logger.info(ACTOR+'Gathering configuration')
        if os.path.isfile(CONFIGFILE):
            NEW = False
            config = configparser.ConfigParser()
            config.read(CONFIGFILE)
            self.Revision = config.get("General", "Revision")
            if config.getboolean("General", "managed"):
                ServerIP = config.get("General", "serverip")
                ServerPort = config.get("General", "serverport")
                ServerURL = "http://"+ServerIP+":"+ServerPort+"/"
            else:
                ServerURL = "NONE"
            logger.info(ACTOR+'Server is located at '+str(ServerURL))
            Location = config.get("Backup", "storagedir")
            logger.info(ACTOR+'Backup location is set to '+str(Location))
        else:
            NEW = True
            self.Revision = 0
            ServerURL = "http://"+ServerIP+":"+ServerPort+"/"
            logger.info(ACTOR+'Server not set in conf file. Using passed in settings '+str(ServerURL))
            Location = "/var/lib/mythtv/bare-client/"
            logger.info(ACTOR+'Backup location not set in conf file. Setting to '+str(Location))

        ## Get last backup time
        if os.path.isfile(Location+"/lastbackuptime.log"):
            lbtf = open(Location+"/lastbackuptime.log")
            lbt = lbtf.readline()
            lbtf.close()
        else:
            logger.info(ACTOR+'lastbackuptime.log does not exist')
            lbt = "NA"

        ## Write check in file
        CHECKINCREATED=False
        try:
            cif = open("/tmp/"+HOSTNAME+"-bare-checkinfile.barelog", 'w')
            cif.write(HOSTNAME+"\t"+lbt+"\tNA\tNA")
            cif.close()
            HOSTNAME=str(platform.node())
            CHECKINCREATED=True
        except:
            logger.debug(ACTOR+"Check in file creation failed")

        ## Push check in file to server
        if CHECKINCREATED:
            logger.info(ACTOR+"Pushing check in file to server")
            pipe = subprocess.Popen(["/usr/share/mythbuntu-bare/bareclient/bare/push_file.py", "http://"+ServerIP+":"+ServerPort+"/cgi-bin/save_file.py", "/tmp/"+HOSTNAME+"-bare-checkinfile.barelog"], stdout=subprocess.PIPE).communicate()
            os.remove("/tmp/"+HOSTNAME+"bare-checkinfile.barelog")
        else:
            logger.info(ACTOR+"Check in file wasn't newly created, skipping file upload")

        ## Check tmp dir for update file
        if os.path.isfile(TMPCONFIGFILE):
            logger.info(ACTOR+'Processing file '+str(TMPCONFIGFILE))
            NEW = False
            self.process_updates()
            os.remove(TMPCONFIGFILE)

        ## Download update file from server
        download_successful=False
        try:
            logger.info(ACTOR+'Checking server for config file')
            self.check_server(TMPCONFIGFILENAME,ServerURL)
            download_successful=True
            logger.info(ACTOR+'Configuration file was downloaded')
        except:
            logger.debug(ACTOR+'Could not download file from server')

        ## If files downloaded from server, get revision and process them
        if download_successful:
            if NEW == False:
                config = configparser.ConfigParser()
                config.read(CONFIGFILE)
                logger.info(ACTOR+'Reading conf file '+str(CONFIGFILE))
                Revision = config.get("General", "Revision")
            else:
                NEW = False
                Revision = 0
            self.process_updates()

        ## Remove temp files
        logger.info(ACTOR+'Removing temp files')
        if os.path.isfile(TMPCONFIGFILE):
            os.remove(TMPCONFIGFILE)
        logger.info(ACTOR+'Update job finished')

    def check_server(self,file_name,base_url):
        from urllib.request import Request, urlopen
        from urllib.error import URLError, HTTPError
        #create the url and the request
        url = base_url + file_name
        req = Request(url)
        logger.info(ACTOR+'Downloading conf file from '+str(url))
        # Open the url
        f = urlopen(req)
        # Open our local file for writing
        local_file = open(TMPCONFIGFILE, "w")
        #Write to our local file
        local_file.write(f.read())
        local_file.close()

    def process_updates(self):
        ## Get revision
        tempconfig = configparser.ConfigParser()
        tempconfig.read(TMPCONFIGFILE)
        logger.info(ACTOR+'Reading conf file '+str(TMPCONFIGFILE))
        tempRevision = tempconfig.get("General", "Revision")
        logger.info(ACTOR+'Configuration file revision is '+str(tempRevision))
        logger.info(ACTOR+'Current revision is '+str(self.Revision))
        ## If revision is newer, process. 
        if int(self.Revision) < int(tempRevision):
            logger.info(ACTOR+'Downloaded file is new')
            ## Calculate checksum
            tempChecksum = tempconfig.get("General", "checksum")
            tempconfig.set("General", "checksum", "XXXXXXXXXX")
            logger.info(ACTOR+'Verifying file integrity')
            with open("/tmp/mythbuntu-bare.tmp", 'w') as conffile:
                tempconfig.write(conffile)
            h = hashlib.sha1()
            f = open("/tmp/mythbuntu-bare.tmp", "rb")
            h.update(f.read())
            hsh = h.hexdigest()
            f.close()
            os.remove("/tmp/mythbuntu-bare.tmp")
            if tempChecksum == hsh:
                logger.info(ACTOR+'Importing new config file')
                ## If checksums match, copy file into dir
                shutil.copyfile(TMPCONFIGFILE, CONFIGFILE)
            else:
                logger.debug(ACTOR+'Error Checksum failed. '+tempChecksum+' '+hsh)
        else:
            logger.info(ACTOR+'Downloaded config file is not new')

if __name__ == "__main__":
    Update().update_job() 
