# -*- coding: utf-8 -*-

import web
from user.model import User, Role, Action
from user.userdecorators import admin
from main.model import OrganizativeUnit, Computer
from formalchemy import FieldSet
from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy import or_

BASE_URL = '/dbadmin'

MODELS = {
        # auth models
        'User': User,
        'Role': Role,
        'Action': Action,

        # opengnsys main models
        'OrganizativeUnit': OrganizativeUnit,
        'Computer': Computer,
        }


class notimpl:
    @admin
    def GET(self, *args, **kwargs):
        return "not implemented"


class Admin:
    @admin
    def GET(self):
        return web.ctx.render.dbadmin.admin(MODELS, BASE_URL=BASE_URL)


class View:
    @admin
    def GET(self, model):
        search = web.input().get('q', '')
        dbmodel = MODELS.get(model, '')
        if not dbmodel:
            raise web.notfound()

        fields = [i for i in dir(dbmodel) if\
                    isinstance(getattr(dbmodel, i), InstrumentedAttribute)]
        if hasattr(dbmodel, 'fields') and callable(getattr(dbmodel, 'fields')):
            fields = dbmodel.fields()

        query = web.ctx.orm.query(dbmodel)
        filters = []
        for i in fields:
            field = getattr(dbmodel, i)
            try:
                filters.append(field.contains(search))
            except:
                pass

        or_clausule = or_(*filters)
        query = query.filter(or_clausule)
        return web.ctx.render.dbadmin.adminview(model, query,
                fields, BASE_URL=BASE_URL)


class Edit:
    @admin
    def GET(self, model, id):
        item = get_item(model, id)
        form = FieldSet(item)
        return web.ctx.render.dbadmin.adminedit("Editar", model, item,
                form, BASE_URL=BASE_URL)

    @admin
    def POST(self, model, id):
        item = get_item(model, id)
        dbmodel = MODELS.get(model, '')
        if not dbmodel:
            raise web.notfound()
        save_edit_form(item)

        raise web.seeother(BASE_URL + '/%s' % model)


class Add:
    @admin
    def GET(self, model):
        dbmodel = MODELS.get(model, '')
        if not dbmodel:
            raise web.notfound()
        form = add_form(dbmodel)

        return web.ctx.render.dbadmin.adminedit(u"Añadir", model,
                None, form, BASE_URL=BASE_URL)

    @admin
    def POST(self, model):
        dbmodel = MODELS.get(model, '')
        if not dbmodel:
            raise web.notfound()
        save_add_form(dbmodel)

        raise web.seeother(BASE_URL + '/%s' % model)


class Del:
    @admin
    def GET(self, model, id):
        item = get_item(model, id)
        web.ctx.orm.delete(item)
        raise web.seeother(BASE_URL + '/%s' % model)


def get_item(model, id):
    dbmodel = MODELS.get(model, '')
    if not dbmodel:
        raise web.notfound()
    orm = web.ctx.orm
    try:
        item = orm.query(dbmodel).get(id)
    except:
        raise web.notfound()
    return item


def edit_form(item):
    form = FieldSet(item)
    form.session = web.ctx.orm
    return form


def save_edit_form(item):
    fieldset = FieldSet(item)
    form = fieldset.bind(data=web.input() or None)
    form.session = web.ctx.orm
    form.sync()
    return form.model


def add_form(dbmodel):
    fieldset = FieldSet(dbmodel)
    item = dbmodel()
    form = fieldset.bind(item, None)
    form.session = web.ctx.orm
    return form


def save_add_form(dbmodel):
    orm = web.ctx.orm
    fieldset = FieldSet(dbmodel)
    item = dbmodel()
    form = fieldset.bind(item, data=web.input() or None)
    form.session = web.ctx.orm
    form.sync()
    orm.add(item)
    return item
