# -*- coding: utf-8 -*-
import os
import sys

from odoo import models, fields, api, exceptions

reload(sys)
sys.setdefaultencoding('utf-8')
PY_TEMPLATE = u'''
# -*- coding: utf-8 -*-
# 项目: jadeDragon-business-center
# 文件: %(file_name)s
# 模块: %(module)s
# Copyright %(year)s JDG 
# Created by %(author)s at %(date_time)s with AutoGenerator


from odoo import models, fields, api, exceptions
class %(class_name)s(models.%(model)s):
    _name = '%(model_name)s'
    _description = u'%(desc)s'
    %(fields)s
    %(func)s
    @api.multi
    def _validate_custom_fields(self):
        return True

    _constraints = [
        (_validate_custom_fields, u'校验不通过', []),
    ]
    _sql_constraints = [
        #('name_uniq', 'unique (name)', u'有重复的名称!')
    ]

    @api.model
    def create(self, values):
        new_values = dict(values)
        if new_values.get('number', '/'):
            new_values.update({
                'number': self.env['ir.sequence'].get(self._name)
            })

        result = super(%(class_name)s, self).create(new_values)
        return result
'''

XML_TEMPLATE = u'''
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <record id="view_%(id_model_str)s_tree" model="ir.ui.view">
            <field name="name">%(model_desc)s列表</field>
            <field name="model">%(model)s</field>
            <field name="arch" type="xml">
                <tree string="%(model_desc)s">
                    %(tree_fields)s
                </tree>
            </field>
        </record>

        <record id="view_%(id_model_str)s_form" model="ir.ui.view">
            <field name="name">%(model_desc)s表单</field>
            <field name="model">%(model)s</field>
            <field name="arch" type="xml">
                <form string="%(model_desc)s">
                    <sheet>
                        <group col="4">
                            %(form_fields)s
                        </group>
                        %(one2many_fields)s
                        <group col="4">
                                <field name="create_uid" string="创建人" attrs="{'readonly':True}"/>
                                <field name="create_date" string="创建日期" attrs="{'readonly':True}"/>
                                <field name="write_uid" string="修改人" attrs="{'readonly':True}"/>
                                <field name="write_date" string="修改日期" attrs="{'readonly':True}"/>
                        </group>
                    </sheet>
                </form>
            </field>
        </record>

        <record id="view_search_%(id_model_str)s" model="ir.ui.view">
            <field name="name">%(model_desc)s查询</field>
            <field name="model">%(model)s</field>
            <field name="arch" type="xml">
                <search>
                    %(search_fields)s
                </search>
            </field>
        </record>

        <record id="action_%(id_model_str)s_list" model="ir.actions.act_window">
            <field name="name">%(model_desc)s</field>
            <field name="res_model">%(model)s</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
            <field name="search_view_id" ref="view_search_%(id_model_str)s"/>
            <field name="view_id" ref="view_%(id_model_str)s_tree"/>
        </record>
    </data>
</odoo>
<!--created with AutoGenerator-->
'''
COMPUTE_FUN_TEMP = '''
    @api.multi
    def %(fun_name)s(self):
        for item in self:
            pass
'''


class ModelCreator(models.Model):
    _name = 'jd.bc.app.model.creator'
    _description = u'Model Creator'

    name = fields.Char(u'模型名称', required=True, index=True)
    desc = fields.Char(u'描述', required=True, index=True)
    type = fields.Selection([('Model', 'Model'), ('TransientModel', 'TransientModel')],
                            default='Model',
                            string=u'类型',
                            required=True)
    column_ids = fields.One2many('jd.bc.app.model.fields',
                                 'parent_id',
                                 string=u'字段')
    model = fields.Char(u'模块', required=True)
    file_name = fields.Char(u'代码文件名称', required=True)

    jdg_app_path = fields.Char(u'应用目录',
                                default=u'/Users/hhl/Desktop/work/jadeDragon-business-center/jdg_app',
                                required=True)

    @api.multi
    @api.onchange('type')
    def on_change_type(self):
        self.ensure_one()
        item = self[0]
        if item.type == 'Model':
            item.column_ids = [
                {'name': 'number',
                 'type': 'char',
                 'str': u'编码',
                 'is_required': True,
                 'is_index': True,
                 'is_search': True,
                 'in_tree': True,
                 'in_form': True},
                {'name': 'name',
                 'type': 'char',
                 'str': u'名称',
                 'is_required': True,
                 'is_index': True,
                 'is_search': True,
                 'in_tree': True,
                 'in_form': True},
                {'name': 'note',
                 'type': 'text',
                 'str': u'备注',
                 'is_required': False,
                 'is_index': False,
                 'is_search': False,
                 'in_tree': False,
                 'in_form': True}
            ]

    @api.multi
    def create_view_code(self):
        self.ensure_one()
        item = self[0]
        module_path = "%s/%s" % (item.jdg_app_path, item.model)
        python_path = "%s/%s/models" % (item.jdg_app_path, item.model)
        views_path = "%s/%s/views" % (item.jdg_app_path, item.model)
        if not os.path.exists(module_path):
            raise exceptions.Warning(u'指定的模块不存在！')
        if not os.path.exists(python_path):
            os.mkdir(python_path)
        if not os.path.exists(views_path):
            os.mkdir(views_path)

        python_file_name = "%s/%s.py" % (python_path, item.file_name)
        view_file_name = "%s/%s.xml" % (views_path, item.file_name)
        if os.path.exists(view_file_name):
            raise exceptions.Warning(u'文件%s已经存在' % view_file_name)

        self.create_view_file(view_file_name)
        return True

    @api.multi
    def create_python_code(self):
        self.ensure_one()
        item = self[0]
        module_path = "%s/%s" % (item.jdg_app_path, item.model)
        python_path = "%s/%s/models" % (item.jdg_app_path, item.model)
        views_path = "%s/%s/views" % (item.jdg_app_path, item.model)
        if not os.path.exists(module_path):
            raise exceptions.Warning(u'指定的模块不存在！')
        if not os.path.exists(python_path):
            os.mkdir(python_path)
        if not os.path.exists(views_path):
            os.mkdir(views_path)

        python_file_name = "%s/%s.py" % (python_path, item.file_name)
        view_file_name = "%s/%s.xml" % (views_path, item.file_name)
        if os.path.exists(python_file_name):
            raise exceptions.Warning(u'文件%s已经存在' % python_file_name)

        self.create_python_file(python_file_name)
        return True

    @api.multi
    def create_model_code(self):
        self.create_python_code()
        self.create_view_code()
        return True

    @api.multi
    def create_view_file(self, xml_file_name):
        self.ensure_one()
        item = self[0]
        id_model_str = item.name.replace(".", "_")
        val = {
            'id_model_str': id_model_str,
            'model_desc': item.desc,
            'model': item.name
        }
        tree_fields = []
        form_fields = []
        search_fields = []
        one2many_fields = []
        one2Many_template = '''
            <page string="%s">
                <field name="%s">
                    <tree editable="bottom">
                    </tree>
                </field>
            </page>
        '''
        for f in item.column_ids:
            if f.in_tree:
                tree_fields.append('<field name="%s"/>' % f.name)
            if f.in_form and f.type != 'one2many' and f.type != 'many2many':
                if f.type == 'many2one':
                    form_fields.append('<field name="%s" options=\"{\'no_create\': True}\"/>' % f.name)
                else:
                    form_fields.append('<field name="%s"/>' % f.name)
            if f.is_search:
                search_fields.append('<field name="%s"/>' % f.name)
            if f.in_form and (f.type == 'one2many' or f.type == 'many2many'):
                one2many_fields.append(one2Many_template % (f.str, f.name))

        tree_fields_str = "\r\n".join(tree_fields)
        form_fields_str = "\r\n".join(form_fields)
        search_fields_str = "\r\n".join(search_fields)
        val.update({
            'tree_fields': tree_fields_str.strip(),
            'form_fields': form_fields_str.strip(),
            'search_fields': search_fields_str.strip(),
            'one2many_fields': '''
                <notebook>
                    %s
                </notebook>
            ''' % "\r\n".join(one2many_fields)
        })
        if not one2many_fields:
            val.update({'one2many_fields': ''})
        xml_file_content = XML_TEMPLATE % val
        xml_file_content = xml_file_content.strip()
        f = open(xml_file_name, 'w')
        f.write(xml_file_content)
        f.close()
        return True

    @api.multi
    def create_python_file(self, python_file_name):
        self.ensure_one()
        item = self[0]
        temp = item.name.split(".")
        model_name = "".join([m_name[0].upper() + m_name[1:] for m_name in temp])
        val = {
            'file_name': python_file_name,
            'module': item.name,
            'year': self._current_year(),
            'author': self._os_user(),
            'date_time': self._current_date_time(),
            'class_name': model_name,
            'model': item.type,
            'model_name': item.name,
            'desc': item.desc,
            'fields': '',
            'func': ''
        }
        fields_content = []
        compute_func_content = []
        for f in item.column_ids:
            field_define_code, compute_func_code = self.create_field_text(f, item.name, item.model)
            fields_content.append(field_define_code)
            compute_func_content.append(compute_func_code)
        val.update({
            'fields': "\r\n    ".join(fields_content),
            'func': "\r\n".join(compute_func_content)
        })
        file_content = PY_TEMPLATE % val
        file_content = file_content.strip()
        f = open(python_file_name, 'w')
        f.write(file_content)
        f.close()
        return True

    @api.model
    def _os_user(self):
        import getpass

        return getpass.getuser()

    @api.model
    def _current_date_time(self):
        import datetime
        import pytz

        tz = pytz.timezone('Asia/Shanghai')
        current = datetime.datetime.now(tz)
        current_time = current.strftime('%Y/%m/%d %H:%M')
        return current_time

    @api.model
    def _current_year(self):
        import datetime
        import pytz

        tz = pytz.timezone('Asia/Shanghai')
        current = datetime.datetime.now(tz)
        current_time = current.strftime('%Y')
        return current_time

    @api.model
    def create_field_text(self, field_define, model_name, module_name):
        '''
        :param field_define:
        :return: (field text, compute function text)
        '''
        fun_text = ''
        text = ''
        field_template = ''
        field_atts = ["string=u'%s'" % field_define.str]
        # 字段属性
        if field_define.compute_func:
            field_atts.append("compute='%s'" % field_define.compute_func)
            fun_text = COMPUTE_FUN_TEMP % {'fun_name': field_define.compute_func}
        if field_define.is_required:
            field_atts.append("required=True")
        if field_define.is_index:
            field_atts.append("index=True")
        if field_define.is_store:
            field_atts.append("store=True")
        if field_define.type == 'char':
            field_template = "%s = fields.Char(%s)"
        elif field_define.type == 'boolean':
            field_template = "%s = fields.Boolean(%s)"
        elif field_define.type == 'one2many':
            if not field_define.relation_column:
                raise exceptions.Warning(u'%[s]的”关联字段“没定义' % field_define.name)
            if not field_define.relation_model:
                raise exceptions.Warning(u'%[s]的”关联模型“没定义' % field_define.name)
            field_template = "%s = fields.One2many(%s)"
            field_atts.insert(0, "'%s'" % field_define.relation_column)
            field_atts.insert(0, "'%s'" % field_define.relation_model)
        elif field_define.type == 'many2one':
            if not field_define.relation_model:
                raise exceptions.Warning(u'%[s]的”关联模型“没定义' % field_define.name)
            field_template = "%s = fields.Many2one(%s)"
            field_atts.insert(0, "'%s'" % field_define.relation_model)
        elif field_define.type == 'text':
            field_template = "%s = fields.Text(%s)"
        elif field_define.type == 'many2many':
            if not field_define.relation_model:
                raise exceptions.Warning(u'%[s]的”关联模型“没定义' % field_define.name)
            field_template = "%s = fields.Many2many(%s)"
            ref_text = model_name.replace(module_name, '').replace(".", "_")
            tmp = field_define.relation_model.split(".")
            right_model_text = ''
            if len(tmp) > 2:
                right_model_text = "_".join(tmp[len(tmp) - 2:])
            else:
                right_model_text = "_".join(tmp)
            ref_table = 'rel_%s_%s' % (ref_text, right_model_text)
            field_atts.insert(0, "'%s'" % field_define.relation_model)
            field_atts.insert(1, "'%s'" % ref_table)
            field_atts.insert(2, "'left_id'")
            field_atts.insert(3, "'right_id'")
        elif field_define.type == 'date':
            field_template = "%s = fields.Date(%s)"
        elif field_define.type == 'datetime':
            field_template = "%s = fields.Datetime(%s)"
        elif field_define.type == 'float':
            field_template = "%s = fields.Float(%s)"
        elif field_define.type == 'integer':
            field_template = "%s = fields.Integer(%s)"
        text = field_template % (field_define.name, ", ".join(field_atts))
        return text.strip(), fun_text


class ModelColumns(models.Model):
    _name = 'jd.bc.app.model.fields'
    _description = u'Model Fields'
    _order = 'sequence'

    parent_id = fields.Many2one('jd.bc.app.model.creator',
                                required=True,
                                string=u'模型',
                                ondelete='cascade')
    name = fields.Char(u'名称', required=True, help=u'字段名称')
    type = fields.Selection([('char', 'Char'),
                             ('one2many', "One2many"),
                             ('boolean', 'Boolean'),
                             ('many2one', "Many2one"),
                             ('many2many', 'Many2many'),
                             ('text', "Text"),
                             ('date', 'Date'),
                             ('datetime', 'Datetime'),
                             ('float', 'Float'),
                             ('integer', 'Integer')],
                            default='char',
                            required=True,
                            string=u'类型')
    str = fields.Char(u'标签', required=True, help=u'Label')
    relation_model = fields.Char(string=u'关联模型', help=u'Many2one和One2many时有用')
    relation_column = fields.Char(string=u'关联字段', help=u'One2many时有用')
    is_required = fields.Boolean(u'必须', default=False)
    is_index = fields.Boolean(u'索引', default=False)
    is_store = fields.Boolean(u'保存', default=False)
    compute_func = fields.Char(u'方法', default='')
    is_search = fields.Boolean(u'查找', default=False)
    in_tree = fields.Boolean(u'列表', default=True)
    in_form = fields.Boolean(u'表单', default=True)
    sequence = fields.Integer(u'排序', help=u'字段排序')
