'''
Disk Image Module
'''

from __future__ import unicode_literals
from ..pluginbase import PluginBase
from ..action import ActionInstance
from main.model import Computer, OrganizativeUnit
import web
import views
import config
from jobs import DiskCurrentStateJob
from clientjob.model import Job

class Plugin(PluginBase):
    '''
    This plugin can save a partition of a computer in a image file.
    This image will be uploaded to a repo. Later you can use those
    images to others computers.
    '''

    def enable(self):
        self.actions_for_url = (
            '/plugin/disk_image/diskprofile/(\d+)/?$', 'removedp',
        )

        self.urls = ('images', views.AdminImages,
                'action/currentstate/(.*)', views.CurrentState,
                'action/assign/(ou|computer)/([^/]*)/', views.AssignDiskProfile,
                'action/adminimages/', views.AdminImages,
                'action/diskprofile/', views.DiskProfileListView,
                'action/savediskstate/asdiskprofile/(\w+)', views.SaveDiskState,
                'diskprofile/list/', views.DiskProfileListView,
                'diskprofile/(\d+)/', views.DiskProfileView,
                'currentstate/computer/(\w+)/force/', views.ForceCurrentState,
                'currentstate/computer/(\w+)', views.CurrentState,
                'newdiskprofile/', views.NewDiskProfile,
                'edit/diskprofile/id/(\w+)', views.EditDiskProfile,
                'view/diskstate/(\w+)', views.DiskState,
                'edit/image/(name|id)/(\w+)', views.EditImage,
                self.get_action_url('removedp'), views.RemoveDiskProfile,
                'diskprofile/restore/(ou|computer)/([^/]*)/', views.RestoreDiskProfile,
                )

    def get_view_disk_state_url(self, jobid):
        return self.fill_url(views.DiskState, jobid)

    def get_new_disk_state_url(self, compname):
        return self.fill_url(views.CurrentState, compname)

    def create_new_current_state(self, computer):
        '''
        Creates a new job to know the disk state of the given computer.
        Returns the id of the created job.
        '''
        job = DiskCurrentStateJob()
        job.send(computer)
        return job.id

    def get_action_instances_for_view(self, view_path, args):
        '''
        Reimplementing function to do more things.
        '''
        functions = []

        if not view_path:
            return []

        if view_path == 'navigator.navigator.NavigatorOrganizativeUnit':
            if args:
                ou_name = args[0]
                functions.append(ActionInstance(self.actions['assign'],
                    self.fill_url(views.AssignDiskProfile, 'ou', ou_name)))

                orm = web.ctx.orm
                ou = orm.query(OrganizativeUnit).filter(
                    OrganizativeUnit.name == ou_name).first()
                if ou.disk_profile:
                    functions.append(ActionInstance(
                        self.actions['viewdiskprofile'],
                        self.fill_url(views.DiskProfileView, ou.disk_profile[0].id)))
                    functions.append(ActionInstance(
                        self.actions['restorediskprofile'],
                        self.fill_url(views.RestoreDiskProfile, 'ou', ou.name)))

        if view_path == 'navigator.navigator.NavigatorComputer':
            # Getting the computer
            computer_name = args[0]

            orm = web.ctx.orm
            computer = orm.query(Computer).filter(
                    Computer.name == computer_name).first()

            if not computer:
                return []

            if computer.online:
                functions.append(ActionInstance(self.actions['currentstate'],
                    self.fill_url(views.CurrentState, computer.name)))

            functions.append(ActionInstance(self.actions['assign'],
                self.fill_url(views.AssignDiskProfile, 'computer', computer.name)))

            if computer.disk_profile:
                functions.append(ActionInstance(
                    self.actions['viewdiskprofile'],
                    self.fill_url(views.DiskProfileView, computer.disk_profile[0].id)))
                functions.append(ActionInstance(
                    self.actions['restorediskprofile'],
                    self.fill_url(views.RestoreDiskProfile, 'computer', computer.name)))
            '''
            else:
                functions.append(ActionsInstance(
                    self.actions['creatediskprofile'],
                    self.get_create_disk_profile_url()))
                functions.append(ActionsInstance(
                    self.actions['associatediskprofile'],
                    self.get_associate_disk_profile_url()))
            '''

        if view_path == 'plugins.disk_image.views.DiskState':
            job_id = args[0]
            job = web.ctx.orm.query(Job)
            job = job.filter(Job.class_name == 'DiskCurrentStateJob')
            job = job.filter(Job.id == job_id).first()

            if not job or job.status != 'FINISHED':
                return []
            functions.append(ActionInstance(self.actions['savediskstate'],
                    self.fill_url(views.SaveDiskState, job_id)))

        return functions

    def get_diskprofile_for_computer(self, computer):
        '''
        Returns which disk profile is assigned to a given computer. If it has none,
        it tries to get it from ancestors (organizative units).
        '''
        if computer.disk_profile:
            # only one, but many to many, a plugin can't create a
            # foreing key in a computer main model
            return computer.disk_profile[0]
        ou = computer.ou
        while ou.parent:
            if ou.disk_profile:
                # only one, but many to many, same as above
                return ou.disk_profile[0]
            ou = ou.parent
        return None

    def fill_data(self, orm):
        from model import DiskProfile, Disk, Image
        from main.model import OrganizativeUnit

        profile = DiskProfile()
        profile.ous.append(orm.query(OrganizativeUnit).filter_by(name='Facultad').one())
        profile.name = u"fdp"
        profile.description = u"First disk profile description :D"
        disk = Disk()
        p = disk.add_partition(size=50, filesystem="NTFS", primary=True, bootable=True)
        p.image = Image(name='image1', filesystem="NTFS")
        p = disk.add_partition(size=10, filesystem="EXT3", primary=False)
        p.image = Image(name='image2', filesystem="EXT3")
        p = disk.add_partition(size=20, filesystem="SWAP", primary=False, bootable=True)
        disk.add_partition(size=10, primary=True)
        profile.add_disk(disk)
        orm.add(disk)
        orm.add(profile)

        orm.commit()
