#!/usr/bin/python
#  -*- coding=utf-8 -*-
"""
This file is part of Pynav.

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

Pynav 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Pynav. If not, see <http://www.gnu.org/licenses/lgpl.html>.

Copyright 2009-2011 Sloft http://bitbucket.org/sloft/pynav

FormDumper use ClientForm HTML parser.
As everyone knows HTML parser are never reliable, so FormDumper may crash because of malformed HTML
"""

from urllib2 import urlopen
from ClientForm import ParseResponse

class FormDumper(object):
    """Dump forms as readable text and pre-generate python dict values
        to use with Pynav go() method"""
       
    def __init__(self, url='', print_all=False, verbose_level=1, handle=None):
        self.verbose_level = verbose_level
        if url is '' and handle is None:
            self.vprint('>USAGE:')
            self.vprint("fd = FormDumper('http://wwwsearch.sourceforge.net/ClientForm/example.html')")
        else:
            if handle:
                self.handle = handle
            else:
                self.handle = urlopen(url)
            self.forms = ParseResponse(self.handle, backwards_compat=False)
            if len(self.forms) > 0:
                self.vprint("\n>There are {forms_number} forms in this page: {forms_list})".format(forms_number=len(self.forms), forms_list=str(range(len(self.forms)))))
                if(print_all):
                    self.dump_all()
                else:
                        self.vprint("\n>Possibilities:")
                        for n in range(len(self.forms)):
                            self.vprint('fd.dump('+str(n)+')')
                        self.vprint("fd.dump_all()\n")
                        if(len(self.forms)==1):
                            self.dump(0)
            else:
                self.vprint('>There is no form in this page')

    def dump(self, form_number):
        """Dump and print (the form number "form_number". Form n°1: fd.dump(0)"""
        form = self.forms[form_number]
        self.vprint(self._prettify_dump(str(form))+"\n")
        self._gen(form)

    def dump_all(self):
        """Dump and print(all forms"""
        self.vprint(len(self.forms), ' forms in this page')
        for form in self.forms:
            self.vprint(self._prettify_dump(str(form))+"\n")
            self._gen(form)
    
    def gen_values(self, form_number):
        """execute the code generated by _string_generated_value()"""
        return eval(self._string_generated_value(self.forms[form_number], inline=False))
    
    def _gen(self, form, inline=True):
        """pre-generate python dict values to use with Pynav go() method"""
        post_dict = ["'"+control.name+"'"+':'+"'"+self._default_value(form, control)+"'" for control in form.controls if control.name is not None]
        self.vprint('values = '+self._string_generated_value(form, inline))
        self.vprint("print b.go('{form_action}', values)\n".format(form_action=form.action))
    
    def _string_generated_value(self, form, inline=True):
        if(inline):
            sep = ', '
        else:
            sep = ",\n"
        post_dict = ["'"+control.name+"'"+':'+"'"+self._default_value(form, control)+"'" for control in form.controls if control.name is not None]
        return '{'+sep.join(post_dict)+'}'
        
    def _default_value(self, form, control):
        value = form.get_value(control.name)
        if(isinstance(value, str)):
           return value
        elif(isinstance(value, list)):
               if(len(value)>0):
                   return value[0]
               else:
                   return ''
        else:
            raise #value type unknown

    def vprint(self, text):
        """Print text is the verbos_level is high enought"""
        if self.verbose_level is 1:
            print text

    def _prettify_dump(self, dump_string):
        dump_string = dump_string.replace('<FileControl(<None>=<No files added>)>>', '(File) No files added')
        dump_string = dump_string.replace('<None>=', '')
        dump_string = dump_string.replace(') (readonly', '')
        dump_string = dump_string.replace('(readonly', '')
        dump_string = dump_string.replace('<', '(')
        dump_string = dump_string.replace('Control(', ') ')
        dump_string = dump_string.replace(')>>', '')
        dump_string = dump_string.replace(')>', '')
        dump_string = dump_string.replace('(POST', '(POST)')
        dump_string = dump_string.replace('(GET', '(GET)')
        dump_string = dump_string.replace('(None>', '')
        return dump_string

