"""
Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms.

Copyright (C) 2023 Antonio de la Rosa Caballero

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
"""

from paramecio2.libraries.lists import SimpleList
from flask import request, redirect, flash
from paramecio2.libraries.urls import add_get_parameters
#from paramecio.citoplasma.mtemplates import set_flash_message
from paramecio2.libraries.formsutils import show_form
from paramecio2.libraries.mtemplates import env_theme, PTemplate
from paramecio2.libraries.i18n import I18n, PGetText
from paramecio2.libraries.formsutils import check_csrf
from collections import OrderedDict

pgettext=PGetText(__file__)
_=pgettext.gettext

#env=env_theme(__file__)

#t=PTemplate(env)

class GenerateAdminClass:
    """Class for insert, update and list items of a model
    """
    
    def __init__(self, model, url, t=None):
        """A class for generate forms, insert and update items from a database model
        
        For an easy and fast access to database data, you can use this class for get a simple database model of paramecio and get list of items, add forms, edit forms and more.
        
        Args:
            model (WebModel): A WebModel model (equivalent to database mysql table)
            url (str): A string with the base url for the forms.
            t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate
            
        Attributes:
            model (WebModel): The webmodel used for generate the admin model form
            t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate
            list (SimpleList): A SimpleList class used for generate the listing
            arr_fields_edit (list): A list with the fields that the user can edit
            url (str): Base url used by GenerateAdminClass for generate edit, insert and other urls.
            template_insert (str): The template used for the insert form
            template_admin (str): The template used for the base admin site
            template_delete (str): The template used for verify delete of an item
            url_redirect (str): The url where user is redirect when an operation is done
            post_update (function): A Function with item id used how argument for make a post-progressing after update.
            
        """
        
        #self.model_name=''
        
        self.model=model
        
        if t:
        
            self.t=t
        else:
            
            env=env_theme(__file__)

            self.t=PTemplate(env)
        
        #self.t.l=pgettext
        
        #self.t.add_filter(self.t._)

        self.list=SimpleList(model, url, self.t)
        
        self.arr_fields_edit=list(model.fields.keys())
        
        del self.arr_fields_edit[self.arr_fields_edit.index(model.name_field_id)]
        
        self.url=url
        
        #self.safe=0;
        
        #self.arr_links={}
        
        #self.hierarchy=None
        
        #self.text_add_item=''
        
        #self.no_insert=False
        
        #self.no_delete=False
        
        self.title=''
        
        #self.id=0
        
        self.template_insert='utils/insertform.phtml'
        
        self.template_admin='utils/admin.phtml'
        
        self.template_verify_delete='utils/verify_delete.phtml'

        self.url_redirect=self.url
        
        self.pre_update=None
        
        self.post_update=None

        self.text_home=_('Home')

    def show(self):
        """ Method for show the admin model
        
        Depending of op_admin arg, you have the different sections of a simple administrator
        
        Returns:
            html (str): The html content of the admin page, can be, items list, forms for create items, etc...
        """
        
        op_admin=request.args.get('op_admin', '0')
        
        item_id=request.args.get('id', '0')
        
        if len(self.model.forms)==0:

            self.model.create_forms()
        
        edit_forms=OrderedDict()
        
        url_action=self.url
        
        for key_form in self.arr_fields_edit:
            edit_forms[key_form]=self.model.forms[key_form]
        
        if op_admin=='1':
            
            post=None
            
            title_edit=_('Add new item')
            
            pass_value=False
            
            if item_id!='0':
                post=self.model.select_a_row(item_id, [], True)
                title_edit=_('Edit item')
                pass_value=True
            
            if post==None or post==False:
                
                if item_id=='0':
                    
                    self.model.model_id=0
                    
                    post={}
                else:
                    return ""
            else:
                self.model.model_id=int(item_id)
            
            url_action=add_get_parameters(self.url, op_admin=2, id=item_id)
            
            form=show_form(post, edit_forms, self.t, False, pass_value)
            
            return self.t.load_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id=item_id, url_action=url_action, enctype=self.model.enctype)
        
        elif op_admin=='2':
            
            check_csrf()
            
            self.model.reset_conditions()
            
            insert_row=self.model.insert
            
            pre_update_ret=False
            
            if not self.pre_update:
                pre_update_ret=True
            else:
                pre_update_ret=self.pre_update(self)
            
            try:
                
                item_id=str(int(request.args.get('id', '0')))
            
            except:
                
                item_id='0'

            title_edit=_('Add new item')
                
            
            if item_id!='0':
                insert_row=self.model.update
                title_edit=_('Edit item')
                self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
            
            post=dict(request.form)
            
            if pre_update_ret:
            
                if insert_row(post):
                    flash(_('Task successful'))
                    
                    if self.post_update:
                        if item_id=='0':
                            item_id=self.model.insert_id()
                        self.post_update(self, item_id)                
                    
                    return redirect(self.url_redirect)
                    
                else:
                    
                    url_action=add_get_parameters(self.url, op_admin=2, id=item_id)

                    post=dict(request.form)
                    
                    form=show_form(post, edit_forms, self.t, True)
                    
                    return self.t.load_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id=item_id, url_action=url_action, enctype=self.model.enctype)

                    
            else:
                url_action=add_get_parameters(self.url, op_admin=2, id=item_id)

                post=dict(request.form)
                
                form=show_form(post, edit_forms, self.t, True)
                
                return self.t.load_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id=item_id, url_action=url_action, enctype=self.model.enctype)

            
            pass
            
        elif op_admin=='3':
            
            verified=request.args.get('verified', '0')
            
            if verified=='1':
    
                if item_id!='0':
                    self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [item_id]]
                    self.model.delete()
                    flash(_('Task successful'))
                    return redirect(self.url_redirect)
    
            else:
                
                return self.t.load_template(self.template_verify_delete, url=self.url, item_id=item_id, op_admin=3, verified=1)
    
        else:
            return self.t.load_template(self.template_admin, admin=self)

    """
    def show_config(self):
        
        
        getpostfiles=GetPostFiles()
        
        getpostfiles.obtain_query()        
        
        op=getpostfiles.query.get('op', '')
        
        object_id=getpostfiles.query.get('id', '0')
        
        c=self.model.select_count
        
        if op=='':
            
            # Show the form
            

            
            return self.t.render_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id=object_id)            
            
    """

class GenerateConfigClass:
    """Class for generate a simple form for simple data for a configuration
    """
    
    def __init__(self, model, url, t):
        """Class for generate a simple form for simple data for a configuration database model
        
        You can use this class if you need a simple table for configurations. You create the model and you can generate the configuration instancing this class in your admin
        
        Args:
            model (WebModel): A WebModel model (equivalent to database mysql table)
            url (str): A string with the base url for the forms.
            t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate
            
        Attributes:
            model (WebModel): The webmodel used for generatre the admin model form
            t (PTemplate): Template used for the class. Normally template subclassed from admin_t PTemplate
            url (str): Base url used by GenerateConfigClass for different sections of update configuration model
            url_redirect (str): The url where user is redirect when an operation is done
            arr_fields_edit (list): A list with the fields that the user can edit
            template_insert (str): The template used for the insert form
            post_update (function): A Function with item id used how argument for make a post-progressing after update.
            text_home (str): A str contening the text of home configuration
        """

        #self.model_name=''
        
        self.model=model
        
        self.title_name=model.label
        
        self.t=t
        
        self.url=url
        
        self.url_redirect=self.url
        
        self.arr_fields_edit=list(model.fields.keys())

        del self.arr_fields_edit[self.arr_fields_edit.index(model.name_field_id)]
        
        self.template_insert='utils/insertform.phtml'

        self.post_update=None

        self.text_home=_('Home')

    def show(self):
        
        """ Method for show the config admin model
        
        Depending of op_config arg, you have the different sections of a simple configuration administrator
        
        """
        
        op_config=request.args.get('op_config', '0')
        
        if len(self.model.forms)==0:

            self.model.create_forms()

        title_edit=_('Edit')+' '+self.title_name

        edit_forms=OrderedDict()

        form_values={}
            
        for key_form in self.arr_fields_edit:
            edit_forms[key_form]=self.model.forms[key_form]

        url_action=add_get_parameters(self.url, op_config=1)
    
        if op_config=='1':
            
            self.model.yes_reset_conditions=False
            
            c=self.model.select_count()

            insert_model=self.model.insert
            
            if c:
                insert_model=self.model.update

            post=dict(request.form)

            if insert_model(post):
                set_flash_message(_('Task successful'))
                self.model.yes_reset_conditions=True
                
                if self.post_update:
                    self.post_update(self)                
                
                redirect(self.url_redirect)
                
                
            else:

                post=dict(request.form)

                form=show_form(post, edit_forms, self.t, True)
                self.model.yes_reset_conditions=True
                return self.t.load_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id='0', url_action=url_action, enctype=self.model.enctype)                
            
        else:
            form_values=self.model.select_a_row_where([], True)
            
            pass_values=True
            
            if not form_values:
                form_values={}
                pass_values=False
            
            form=show_form(form_values, edit_forms, self.t, True, pass_values)            
            
            return self.t.load_template(self.template_insert, admin=self, title_edit=title_edit, form=form, model=self.model, id=0, url_action=url_action, enctype=self.model.enctype)
        
