from __future__ import unicode_literals
from db import connect
from clientjob.model import Job
from plugins.disk_image.model import (DiskProfile, Disk, Image,
                                      Partition, get_assigned_disk_profile)
from decorators import pi18n
from utils import adquire_thread_orm
from main.model import Computer, OrganizativeUnit
import json
import web

class DiskCurrentStateJob(Job):
    '''
    This job is sent when the user wants to see the partitions of a
    computer. The reply will have the next format:

    1 3940272 EXT2:3935893 EMPTY:0 EMPTY:0 EMPTY:0
    2 15761088 EXT2:15759733 EMPTY:0 EMPTY:0 EMPTY:0
    3 1948672 FAT32:506880 EXTENDED:1181696 EMPTY:0 EMPTY:0 EXT3:498688 XFS:328704 LINUX-SWAP:351232

    This reply will be used by CurrentStateDisk view to show to the
    user this information.
    '''

    __command__ = 'GetDiskProfile'

    def __init__(self):
        Job.__init__(self, self.__command__, type="ogr")

    @pi18n
    def get_user_message(self):
        '''
        We show a better message when the job is finished.
        For 15 minutes the message will have a link to the view
        where the images will be created. After of that 15 minutes
        the link won't appear any more to avoid, more than possible,
        unexpected behavior.
        '''
        if self.status != 'FINISHED':
            Job.get_user_message(self)

        # WARNING! web.ctx.plugin_manager is not available in the server daemon
        if self.status != 'FINISHED' or not hasattr(web.ctx, 'plugin_manager'):
            return Job.get_user_message(self)

        image_disk = web.ctx.plugin_manager.get_plugin_by_name('disk_image')

        return _('Retrieved the <a href=\"%s\">current disk state %s</a>') %\
            (image_disk.get_view_disk_state_url(self.id),
                    self.computer.name)

    @pi18n
    def generate_profile(self):
        orm = adquire_thread_orm()
        profile = DiskProfile()
        bname = _(u'%(comp)s disk profile') % dict(comp=self.computer.name)
        pname = bname

        t = 0
        while orm.query(DiskProfile).filter_by(name=pname).count():
            pname = bname + u'%d' % t
            t += 1
        profile.name = pname

        profile.description = _(u'%(comp)s disk profile') % dict(comp=self.computer.name)
        profile.from_str(self.client_message)
        return profile

class CreateImageJob(Job):
    '''
    This job is sent when the user want create a image from a computer's
    partition. A image is given in the constructor, when the job is finished
    correctly so the image is added definitively in the database.
    '''
    __command__ = 'CreateImageProgress'

    def __init__(self, partitionid, computerid):
        orm = adquire_thread_orm()
        self.computer = orm.query(Computer).get(computerid)
        partition = orm.query(Partition).get(partitionid)

        dnumber = partition.disk.number
        pnumber = partition.number
        bimgname = '%s_disk%s_part%s' % (self.computer.name, dnumber, pnumber)
        imgname = bimgname
        args = [str(dnumber), str(pnumber), 'REPO', imgname]

        # unique name
        t = 0
        while orm.query(Image).filter_by(name=imgname).count():
            imgname = bimgname + u'_%d' % t
            t += 1
        image = Image(name=imgname, filesystem=partition.filesystem)
        image.repos.append(self.computer.get_repo())
        orm.commit()
        partition.image = image
        orm.commit()

        Job.__init__(self, self.__command__, args=args, type='ogr', sequential=True)

    @pi18n
    def get_user_message(self):
        if self.status != 'FINISHED':
            return _("All ok")

        #return _('<a href=\"%s\">The image</a>was created sucessfully.') %\
        #        web.ctx.plugin_manager.get_plugin_by_name('diskimage').\
        #        get_edit_image_by_id_url(self.image_id)


class CloneJob(Job):
    def __init__(self, computerid):
        super(CloneJob, self).__init__()
        orm = adquire_thread_orm()
        computer = orm.query(Computer).get(computerid)
        profile = computer.disk_profile[0]
        for disk in profile.get_disks():
            for partition in disk.get_partitions_order_by_position():
                if "SWAP" in partition.filesystem.upper():
                    continue
                job = CreateImageJob(partition.id, computer.id)
                self.children.append(job)

    @pi18n
    def get_user_message(self):
        orm = adquire_thread_orm()
        if self.status == 'FINISHED':
            return _("Cloned images successfully")
        else:
            return super(CloneJob, self).get_user_message()


class RestoreDiskProfileJob(Job):
    '''
    This job creates partitions and restores disk images in a
    computer or ou
    '''

    # that's no executed in client, it's a parent job
    __command__ = 'RestoreDiskProfile'

    def __init__(self, entity, entityid):
        super(RestoreDiskProfileJob, self).__init__(self.__command__, sequential=True)
        orm = adquire_thread_orm()

        if entity == 'ou':
            # for each computer in this ou
            ou = orm.query(OrganizativeUnit).get(entityid)
            for computer in ou.get_all_descendant_computers():
                job1 = CreatePartitionsJob(computer.id)
                job2 = RestoreImagesJob(computer.id)
                self.children.append(job1)
                self.children.append(job2)

        else:
            computer = orm.query(Computer).get(entityid)
            job1 = CreatePartitionsJob(computer.id)
            job2 = RestoreImagesJob(computer.id)
            self.children.append(job1)
            self.children.append(job2)


class RestoreImagesJob(Job):
    '''
    Launch one subjob for each image
    '''

    # that's no executed in client, it's a parent job
    __command__ = 'RestoreImages'

    def __init__(self, computerid):
        super(RestoreImagesJob, self).__init__(self.__command__, sequential=True)

        orm = adquire_thread_orm()
        computer = orm.query(Computer).get(computerid)

        profile = get_assigned_disk_profile(computer)

        for disk in profile.get_disks():
            for partition in disk.get_partitions_order_by_position():
                if not partition.image:
                    continue

                job = RestoreImageJob(partition.id, computerid)
                self.children.append(job)


class RestoreImageJob(Job):
    __command__ = 'RestoreImageProgress'

    def __init__(self, partitionid, computerid):

        orm = adquire_thread_orm()
        self.computer = orm.query(Computer).get(computerid)
        partition = orm.query(Partition).get(partitionid)

        dnumber = partition.disk.number
        pnumber = partition.number
        image = partition.image
        args = ['REPO', partition.image.name, str(dnumber), str(pnumber)]

        super(RestoreImageJob, self).__init__(self.__command__,
                            type='ogr', args=args, sequential=True)


class CreatePartitionsJob(Job):
    '''
    Launch one subjob for each disk to create partitions
    '''

    # that's no executed in client, it's a parent job
    __command__ = 'CreatePartitions'

    def __init__(self, computerid):
        super(CreatePartitionsJob, self).__init__(self.__command__, sequential=True)

        orm = adquire_thread_orm()
        computer = orm.query(Computer).get(computerid)

        profile = get_assigned_disk_profile(computer)

        for disk in profile.get_disks():
            job = CreatePartitionJob(disk.id, computerid)
            self.children.append(job)


class CreatePartitionJob(Job):
    __command__ = 'CreatePartitionsPercentage'

    def __init__(self, diskid, computerid):
        orm = adquire_thread_orm()
        self.computer = orm.query(Computer).get(computerid)
        disk = orm.query(Disk).get(diskid)

        args_str = disk.to_str()
        args = [unicode(disk.number)] + args_str.split(' ')

        super(CreatePartitionJob, self).__init__(self.__command__,
                            type='ogr', args=args, sequential=True)
