import sys
import os
import subprocess

###################################################################################
# logs could be stored in the JFFS2 partition or the SD card p3 partition
###################################################################################

class SetLogging():
    def __init__(self, log1):
        #path for the partition3 in the SD card
        self.SDPART3="/media/mmcblk0p3"
        #final flags to indicated which device being used
        self.jffsmounted=False
        self.sdmounted=False
        #the basenames of the log files
        self.mainlog = "main_update.log"
        self.measlog = "meas_update.log"
        self.srclog = "src_update.log"
        self.log1 = log1
        #all the meaningful(hoping) output from the functions in this logfile
        self.upgmntlog = open("/home/root/upgmnt.log", "w+")
        self.logbasename = "upgmnt.log"
        
        #if JFFS2 nor the SDPART3 is not mounted then use ramdisk /home/root
        self.homemount="/home/root"
        #JFFS2 partition mounted path
        self.jffsmount="/mnt/flash"
        #JFFS2 partition used as a block device
        self.jffsblock="/dev/mtdblock4"
        #JFFS2 partition used as a char device
        self.jffschar="/dev/mtd4"
        #upg1 used in the JFFS2 partition
        self.upgdir1="/mnt/flash/upg1"
        #upg2 used in the JFFS2 partition
        self.upgdir2="/mnt/flash/upg2"
        #upg1 used in the SD card partition3
        self.upgsd1="/media/mmcblk0p3/upg1"
        #upg2 used in the SD card partition3
        self.upgsd2="/media/mmcblk0p3/upg2"
        #marker to indicate where was upgrade logs stored the last time
        self.upgmarker="upgmarker"
        #status to indicated the upgrade was successfully completed
        #when the upgrade starts it would be incremented and after finishing the upgrade, counter is decremented
        #ideally this file should always contain 0
        self.upgstatus="upgstatus"
        #counts the total number of upgrades on this box(or the host board to be exact)
        self.upgcount="totalupgrades"
        #prefix used by the getlogn.sh for retrieving the upgrade logs
        #prefix could contain mounted path for the JFFS2 or the SD card partition3
        self.upgprefix="/home/root/upgprefix"
        #mount prefix where the these logs should be stored
        #either /mnt/flash or /media/mmcblk0p3 or ""
        self.upgmount=""
        #prefix will be /mnt/flash/upg1 or /mnt/flash/upg2
        self.prefix=""
        

    def CheckJFFS2(self):
#check for /mnt/flash
#mount the mtdblock4 on /mnt/flash
#if mount fails, format the mtdblock4 partition
#try mount again
#if it fails, return False, else return True
#assuming /mnt always exists
        if os.path.exists(self.jffsmount) != 1:
            try:
                os.mkdir(self.jffsmount)
            except Exception as e:
                self.upgmntlog.write("%s exception %s\n" % (self.jffsmount, e))
                return False,""
        #assuming /dev/mtblock4 is always mounted on /mnt/flash
        if os.path.ismount(self.jffsmount):
            self.upgmntlog.write("%s already mounted \n" % self.jffsmount)
            self.jffsmounted=True
        else:
            mountjffs = "mount -t jffs2 " + self.jffsblock + " " + self.jffsmount
            p1 = subprocess.Popen([mountjffs], stdout=self.upgmntlog, stderr=self.upgmntlog, shell=True)
            status = p1.wait()
            if status != 0:
                self.upgmntlog.write("%s cmd fail %d \n" % (mountjffs, status))
                #try mounting after formatting the partition
                formatjffs = "flash_eraseall -j " + self.jffschar
                p1 = subprocess.Popen([formatjffs], stdout=self.upgmntlog, stderr=self.upgmntlog, shell=True)
                status = p1.wait()
                if status != 0:
                    self.upgmntlog.write("%s cmd fail\n" % (formatjffs))
                    return False, ""
                #formatted successfully try mounting again
                p1 = subprocess.Popen([mountjffs], stdout=self.upgmntlog, stderr=self.upgmntlog, shell=True)
                status = p1.wait()
                if status != 0:
                    self.upgmntlog.write("%s cmd fail second \n" % (mountjffs))
                    return False, ""
                else:
                    self.upgmntlog.write("%s mounted successfully second\n " % (mountjffs))
                    self.jffsmounted=True
            else:
                self.upgmntlog.write("%s mounted successfully \n" % (mountjffs))
                self.jffsmounted=True

        if self.jffsmounted:
            self.upgmntlog.close()
            logpath = self.jffsmount + "/" + self.logbasename
            self.upgmntlog = open(logpath, "w+")
            self.upgmntlog.write("logpath %s \n" % logpath)
                #check upg1 or upg2
            if os.path.exists(self.upgdir1) != 1:
                try:
                    os.mkdir(self.upgdir1)
                except Exception as e:
                    self.upgmntlog.write("%s mkdir fail %s\n" % (self.upgdir1, e))
                    return False,""
            if os.path.exists(self.upgdir2) != 1:
                try:
                    os.mkdir(self.upgdir2)
                except Exception as e:
                    self.upgmntlog.write("%s mkdir fail %s\n" % (self.upgdir2, e))
                    return False, ""
                        
            mark1 = self.upgdir1 + "/" + self.upgmarker
            mark2 = self.upgdir2 + "/" + self.upgmarker

            if os.path.exists(mark1) != 1 and os.path.exists(mark2) != 1:
                    #create a marker in upg1
                self.upgmntlog.write("using %s initially \n" % (mark1))
                m1 = open(mark1, "w+")
                m1.close()
                prefix = self.upgdir1
                return True, prefix          
            elif os.path.exists(mark1) == 1:
                self.upgmntlog.write("using %s \n " % (mark1))
                os.remove(mark1)
                m2 = open(mark2, "w+")
                m2.close()
                prefix = self.upgdir2
                return True, prefix          
            elif os.path.exists(mark2) == 1:
                self.upgmntlog.write("using %s  \n" % (mark2))
                os.remove(mark2)
                m1 = open(mark1, "w+")
                m1.close()
                prefix = self.upgdir1
                return True, prefix          
            else:
                return False,""
        return True,""


    def CheckSDPartition3(self):
        """
        Assuming the partition3 is present it is already mounted on /media/mmcblk0p3
        """
        if os.path.exists(self.SDPART3) == 1 and os.path.ismount(self.SDPART3):
            self.sdmounted = True

        if self.sdmounted:
            self.upgmntlog.close()
            logpath = self.SDPART3 + "/" + self.logbasename
            self.upgmntlog = open(logpath, "w+")
            self.upgmntlog.write("logpath %s \n" % logpath)
            if os.path.exists(self.upgsd1) != 1:
                try:
                    os.mkdir(self.upgsd1)
                except Exception as e:
                    self.upgmntlog.write("%s mksddir fail %s\n" % (self.upgsd1, e))
                    return False,""
            if os.path.exists(self.upgsd2) != 1:
                try:
                    os.mkdir(self.upgsd2)
                except Exception as e:
                    self.upgmntlog.write("%s mksddir fail %s\n" % (self.upgsd2, e))
                    return False, ""

            mark1 = self.upgsd1 + "/" + self.upgmarker
            mark2 = self.upgsd2 + "/" + self.upgmarker

            if os.path.exists(mark1) != 1 and os.path.exists(mark2) != 1:
                self.upgmntlog.write("using %s initially \n" % (mark1))
                m1 = open(mark1, "w+")
                m1.close()
                prefix = self.upgsd1
            elif os.path.exists(mark1) == 1:
                self.upgmntlog.write("using %s \n " % (mark1))
                m2 = open(mark2, "w+")
                m2.close()
                os.remove(mark1)
                prefix = self.upgsd2
            elif os.path.exists(mark2) == 1:
                self.upgmntlog.write("using %s  \n" % (mark1))
                m1 = open(mark1, "w+")
                m1.close()
                os.remove(mark2)
                prefix = self.upgsd1
            return True, prefix         
        else:
#It is assumed that if the partition3 is present it would be mounted at /media/mmcblk0p3 by udev at the start up
#if it is not mounted, it is assumed either the firmware is 1.2.6.7 or earlier software so there is no p3 partition for the logs
#the script is not retrying to remount the partition here
            return False,""


#Increment before starting the upgrade
    def UpgStartIncr(self):
        self.upgmntlog.write("Incr using %s mount \n" % self.upgmount)
        fname = self.upgmount + "/" + self.upgstatus
        self.upgmntlog.write("Incr fname %s  \n" % fname)
        upg = open(fname, "a+")
        #position at the start of the file
        upg.seek(0, 0)
        #read 10 characters
        line=upg.read(10)
        if line.strip("\n ") == "":
            num=1
        else:
            num=int(line.strip("\n "), 0)
            self.upgmntlog.write("Incr status num %d \n" % num)
            num=num+1
        upg.close()
        #open it again for erasing the file and writing the number
        upg = open(fname, "w+")
        upg.write("%d\n" % num)
        upg.close()


#Decrement after finishing the upgrade
    def UpgEndDecr(self):
        self.upgmntlog.write("Decr using %s mount \n" % self.upgmount)
        fname = self.upgmount + "/" + self.upgstatus
        self.upgmntlog.write("Decr fname %s  \n" % fname)
        upg = open(fname, "a+")
        #position at the start of the file
        upg.seek(0, 0)
        #read 10 characters
        line=upg.read(10)
        if line.strip("\n ") == "":
            num=0
        else:
            num=int(line.strip("\n "), 0)
            self.upgmntlog.write("Decr status num %d \n" % num)
            num=num-1
        upg.close()
        #open it again for erasing the file and writing the number
        upg = open(fname, "w+")
        upg.write("%d\n" % num)
        upg.close()


    def IncrTotalUpg(self):
        self.upgmntlog.write("total incr using %s mount \n" % self.upgmount)
        fname = self.upgmount + "/" + self.upgcount
        upg = open(fname, "a+")
        self.upgmntlog.write("total incr fname %s  \n" % fname)
#pos    ition at the start of the file
        upg.seek(0, 0)
#rea    d 10 characters
        line=upg.read(10)
        if line.strip("\n ") == "":
            num=1
        else:
            num=int(line.strip("\n "), 0)
            self.upgmntlog.write("total incr status num %d \n" % num)
            num=num+1
        upg.close()
#ope    n it again for erasing the file and writing the number
        upg = open(fname, "w+")
        upg.write("%d\n" % num)
        upg.close()

    def ReadUpgPrefix(self):
        fname=""
        try:
            readfd = open(self.upgprefix, "r+")
        except Exception as e:
            print "upgprefix exception %s " % e
        else:
            readfd.seek(0, 0)
            fname = readfd.readline()
            if fname == "":
    #this file would be present in /home/root
                self.upgmntlog.write("upgprefix is empty %s \n" % fname)
            else:
                self.upgmntlog.write("upgprefix = %s \n" % fname)
            readfd.close()
        return fname.strip()


#write the prefix which is used by the getlogn.sh
#could be either /mnt/flas or /media/mmcblk0p3 or "/home/root"
    def WriteUpgPrefix(self, prefixpath):
#erase the existing content
        upgprefixfd = open(self.upgprefix, "w+")
        upgprefixfd.write("%s\n" % prefixpath)
        upgprefixfd.close()

    def CheckNVMount(self):
        """
        if jffs2 partition can be mounted have the logs in the /mnt/flash
        if mmcblk0p3 exists have the logs in the /media/mmcblk0p3
        nothing else store the files in the ramdisk
        do not have to do this check from x.y.x (where x > 2 && y > 0 && z > 0)
        CHECK FOR PASS-BY-REFERENCE
        """
        fname = self.ReadUpgPrefix()
        if fname == "":
            self.jffsmounted, self.prefix = self.CheckJFFS2()
            if not self.jffsmounted:
                self.sdmounted, self.prefix  = self.CheckSDPartition3()
                if self.sdmounted:
                    self.upgmount=self.SDPART3
                else:
                    self.upgmount=self.homemount
            else:
                self.upgmount=self.jffsmount
    #for the SD card preference over the JFFS2
    #        self.sdmounted, prefix = self.CheckSDPartition3()
    #        if not self.sdmounted:
    #            self.jffsmounted, prefix  = self.CheckJFFS2()
    #            if self.jffsmounted:
    #                self.upgmount=self.jffsmount
    #            else:
    #                self.upgmount=self.homemount
    #        else:
    #            self.upgmount=self.SDPART3
    
            self.WriteUpgPrefix(self.prefix)
        else:
#prefix would be /mnt/flash/upg1 or /mnt/flash/upg2
            self.prefix = fname
            dirname = os.path.dirname(self.prefix)
            self.upgmntlog.close()
            self.upgmount = dirname
#only the recent logfile is maintained
            logpath = dirname + "/" + self.logbasename
            self.upgmntlog = open(logpath, "w+")
            self.upgmntlog.write("logpath %s \n" % logpath)
            self.upgmntlog.write("using the existing prefix %s fname %s\n" % (self.prefix, fname))
    

        #prefix would be like /mnt/flash/upg1 or /mnt/flash/upg2 for jffs2
        #prefix would be like /media/mmcblk0p3/upg1 or /media/mmcblk0p3/upg2 for jffs2
        self.mainlog = self.prefix + "/" + self.mainlog
        self.measlog = self.prefix + "/" + self.measlog
        self.srclog  = self.prefix + "/" + self.srclog
        self.log1    = self.prefix + "/" + self.log1
        self.upgmntlog.write("using %s for logs prefix %s \n" % (self.upgmount, self.prefix))
        self.upgmntlog.write("main = %s meas = %s src = %s log1 = %s \n" % 
                (self.mainlog, self.measlog, self.srclog, self.log1))


    def GetAllLogs(self):
        return self.mainlog, self.measlog, self.srclog, self.log1

    def GetPrefix(self):
        return self.prefix

    def CloseLog(self):
        self.upgmntlog.close()

if __name__ == "__main__":
    setlog = SetLogging("fw_update.log")
    setlog.CheckNVMount()
    main,meas,src,log1 = setlog.GetAllLogs()
    print "main=%s meas=%s src=%s log1=%s\n" % (main, meas, src, log1)
    print "prefix = %s \n" % setlog.GetPrefix()

    setlog.UpgStartIncr()
    setlog.UpgEndDecr()
    setlog.IncrTotalUpg()
#close the logging for this module
    setlog.CloseLog()

