# -*- encoding: utf-8 -*-
# © 2014 Elico Corp (https://www.elico-corp.com)
# Licence AGPL-3.0 or later(http://www.gnu.org/licenses/agpl.html)


from datetime import datetime
import time
from osv import fields, osv
from tools.translate import _
from tools import ustr
#import tools


class gap_analysis_effort(osv.Model):
    _name = "gap_analysis.effort"
    _description = "Gap Analysis Efforts"
    
    _columns = {
        'name':     fields.char('Effort', size=4, required=True,),
        'unknown':  fields.boolean('Undefined duration ?', help='If checked, when this effort is used, the user would have to specify the duration manually.'),
        'duration': fields.float('Duration (hour)', help='Duration in hour for this effort.', required=True,),
    }
    
    def onchange_unknown(self, cr, uid, ids, unknown):
        val = {}
        val['unknown'] = unknown
        if not unknown:
            val['duration'] = 0.0
        return {'value': val}
    
    _order = 'name'


class gap_analysis_workload_type(osv.Model):
    _name = "gap_analysis.workload.type"
    _description = "Gap Analysis Workload Type"
    
    _columns = {
        'name':     fields.char('Name', size=64, required=True, translate=True),
        'category': fields.selection([('Functional Analysis','Functional'), ('Technical Analysis','Technical')], 'Analysis', required=True,),
        'code':     fields.char('Code for Report', size=8, required=True, translate=True, help="Set the code if name is too long (eg: in reports)."),
        'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of workload type."),
        'duration': fields.float('Duration (hour)', help='Default duration in hour for this type of workload.', required=True,),
    }
    _defaults = {
        'sequence': 10,
        'category': 'Functional Analysis',
        'duration': 4,
    }
    _order = 'sequence'



class gap_analysis_workload(osv.Model):
    _name = "gap_analysis.workload"
    _description = "Gap Analysis Workload"
    
    _columns = {
        'gap_line_id': fields.many2one('gap_analysis.line', 'Gap-analysis Line', ondelete='cascade', select=True, readonly=True),
        'fct_id':      fields.many2one('gap_analysis.functionality', 'Gap-analysis Functionality Template', ondelete='cascade', select=True, readonly=True),
        'type':        fields.many2one('gap_analysis.workload.type', 'Type', required=True, select=True),
        'duration':    fields.float('Duration (hour)', help='Duration in hour for this task.', required=True,),
    }
    
    def onchange_type_id(self, cr, uid, ids, type_id):
        val = {}
        my_type = self.pool.get('gap_analysis.workload.type').browse(cr, uid, type_id)
        val['duration'] = my_type.duration
        return {'value': val}
    



class gap_analysis_functionality_category(osv.Model):
    _inherit = "product.category"
    _name = "gap_analysis.functionality.category"
    _description = "Gap Analysis Functionality Categories"
    
    
    def _category_to_update(self, cr, uid, ids, fields=None, arg=None, context=None):
        if type(ids) != type([]):
            ids = [ids]
        return self.pool.get('gap_analysis.functionality.category').search(cr, uid, [], order='parent_left') or []
    
    def _name_get_full_path(self, cursor, uid, ids, fields, arg, context=None):
        result = {}
        for category in self.browse(cursor, uid, ids):
            full_path = ''
            current_category = category
            while current_category:
                if full_path=='':
                    full_path = ustr(current_category.name)
                else:
                    full_path = ustr(current_category.name) + ' / ' + full_path
                current_category = current_category.parent_id or False
            result[category.id] = full_path
        return result
    
    
    _columns = {
        'parent_id':   fields.many2one('gap_analysis.functionality.category','Parent Category', select=True, ondelete='cascade'),
        'child_id':    fields.one2many('gap_analysis.functionality.category', 'parent_id', string='Child Categories'),
        'code':        fields.char('Code', size=8, required=True, help="Use for functionality sequencing."),
        'full_path':   fields.function(_name_get_full_path, type="char", method=True, size=2048, store={'gap_analysis.functionality.category': (_category_to_update, ['name','parent_id'], 10)}, string='Name'),
    }
    
    def _check_recursion(self, cr, uid, ids, context=None):
        level = 100
        while len(ids):
            cr.execute('select distinct parent_id from gap_analysis_functionality_category where id IN %s',(tuple(ids),))
            ids = filter(None, map(lambda x:x[0], cr.fetchall()))
            if not level:
                return False
            level -= 1
        return True

    _constraints = [
        (_check_recursion, 'Error ! You cannot create recursive categories.', ['parent_id'])
    ]
    
    _parent_name = "parent_id"
    _parent_store = True
    _parent_order = 'sequence, name'
    _order = 'parent_left'



class gap_analysis_functionality(osv.Model):

    _name = "gap_analysis.functionality"
    _description = "Gap Analysis Functionalities"
    
    _columns = {
        'name':        fields.char('Functionality', size=256, required=True, translate=True),
        'description': fie
lds.text('Description'),
        'category':    fields.many2one('gap_analysis.functionality.category', 'Category', required=True, select=True),
        'is_tmpl':     fields.boolean('Template ?', help='This Functionality is a Template ?'),
        'proposed':    fields.boolean('Propose as template ?'),
        #### Default values (Templating) ####
        'workloads':   fields.one2many('gap_analysis.workload', 'fct_id', 'Default Workloads'),
        'openerp_fct': fields.many2one('gap_analysis.openerp', 'Default OpenERP feature', select=True),
        'critical':    fields.integer('Default Critical Level', help='Indicator to specify the importance of this functionality in the project.'),
        'testing':     fields.float('Test (hour)'),
        'effort':      fields.many2one('gap_analysis.effort', 'Default Effort', help="Development Effort for this functionality."),
        'duration_wk': fields.float('Default Duration (hour)', help='Since this effort has no pre-defined duration, you must set one.'),
        'unknown_wk':  fields.boolean('Must set the duration manually ? (Default)',),
    }
    
    def onchange_effort_id(self, cr, uid, ids, effort_id, unknown_wk):
        val = {}
        my_effort = self.pool.get('gap_analysis.effort').browse(cr, uid, effort_id)
        val['unknown_wk'] = my_effort.unknown
        return {'value': val}
    
    
    def write(self, cr, uid, ids, vals, context=None):
        if 'is_tmpl' in vals and vals['is_tmpl'] == True:
            vals['proposed'] = False
        return super(gap_analysis_functionality, self).write(cr, uid, ids, vals, context=context)


class gap_analysis_openerp(osv.Model):
    _name = "gap_analysis.openerp"
    _description = "Gap Analysis OpenERP features"
    
    _columns = {
        'name':       fields.char('OpenERP feature', size=256, required=True, translate=True),
    } 


class gap_analysis(osv.Model):
    _name = "gap_analysis"
    _description = "Gap Analysis"
    
    def _estimated_time_cost(self, cursor, uid, ids, fields, arg, context=None):
        result = {}
        for gap in self.browse(cursor, uid, ids):
            res = {}
            res['estimated_time'] = 0.0
            res['estimated_cost'] = 0.0
            
            for gap_line in gap.gap_lines:
                if gap_line.keep:
                    res['estimated_time'] += gap_line.total_time
                    res['estimated_cost'] += gap_line.total_cost
                
            result[gap.id] = res
        return result
    
    
    def _sorted_distinct_workloads(self, cursor, uid, ids, arg, context=None):
        result = {}
        for gap in self.browse(cursor, uid, ids):
            types = []
            line_ids = [l.id for l in gap.gap_lines]
            if line_ids:        
 