# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - SaveMailTo macro

    @copyright: 2007 Richard Flieger
    @contact: < e DASH mail AT rf DASH mmx DOT de >
    @license: GNU GPL, see COPYING for details.
    
    Description:
    
        Outputs from the given email an image to disable spam robots.
        Replaces AT, DOT and DASH, strips blanks and ALLUPPERCASE words.
        On every request a new image is generated.
    
    History:
    
        2007/04/17 0.2.1:  some refactoring
        2007/04/02 0.2b: Beta, new features
        2007/03/18 0.1b: Beta, dirty hack
        
        
    Features:
    
        * letters
            * rotate letters
            * random color
            * move letters
        * different spacing
        * lines
            * random line-color
            * fixed line-color
            * random line position
            * lines in front and/or background
        * background
            * random bg-color
            * fixed bg-color
        * split image
            * fixed pieces
            * random pieces
        * small java-script for clicking
        * link for refreshing the image
            * configurable
        * unique image name
        * easier configuration
   
"""

import re, sha
from MoinMoin.Page import Page
from MoinMoin import user
from MoinMoin.action import AttachFile
import Image, ImageDraw, ImageFont, ImageOps
from MoinMoin.util.mail import decodeSpamSafeEmail
import random

Dependencies = [""]

class UserList:
    
    ############################################################################
    ##
    ##  Configuration
    ##
    ############################################################################
    
    ## E-Mail Link
    ## -------------------------------------------------------------------------
    ## Enable or disable javascript for email-link
    javascript_enable = True
    
    ## Link below the image, for refreshing the image
    refesh_text = u"refresh email-image"
    
    ## Text
    ## -------------------------------------------------------------------------
     ## Font
     ## You can also define your own font
    font = u"lubB24.pil"
        
     ## Range of random space between every letter
     ## ( from, to )
    space = 0,10
    
     ## Rotate a little bit, do some trick if you want
     ## Range of degrees for rotation of every letter
     ## ( from, to )
    letter_rotate_range = -20, 20
    
     ## rgb color range ( from, to )
    letter_color_red = 150, 150 ## red
    letter_color_green = 200, 256 ## green
    letter_color_blue = 150, 150 ## blue

    ## Background
    ## -------------------------------------------------------------------------

    ## Backgournd-Color
    
     ## fixed
    enable_fixed_bg_color = True
     ## rgb color (red,green,blue)
    bg_color_fixed = 100, 165, 79
    
     ## random
    enable_random_bg_color = False
     ## rgb color random range ( from, to )
    bg_color_red = 120, 120 ##red
    bg_color_green = 120, 120 ## green
    bg_color_blue = 80, 140 ## blue
    
    ## Lines
    enable_lines_in_bg = True
    enable_lines_in_font = False
     ## fixed
    enable_fixed_line_color = False
     ## rgb color (red,green,blue)
    line_color_fixed = 0, 0, 0
    
     ## random
    enable_random_line_color = True
     ## rgb color random range ( from, to )
    line_color_red = 100, 100 ##red
    line_color_green = 120, 250 ## green
    line_color_blue = 100, 100 ## blue

    enable_split_image = True

    entrys = 15
    
    ############################################################################
    ##
    ##  End of configuration
    ##
    ############################################################################
    
    
    Dependencies = Dependencies
    
    def __init__( self, macro, email ):
        self.request = macro.request
        self.formatter = macro.formatter
        self.pagename = macro.formatter.page.page_name
        self.email = email

    def getSpace(self):
        """
            return the random size of space between a letter
        """
        return random.randint(self.space[0], self.space[1])


    def getLetterImage(self, letter):
        """
            generate from a single letter a image
        """
        # Create a dummy image 1x1
        im = Image.new("RGBA", (1, 1))
        draw = ImageDraw.Draw(im)
        lettersize = draw.textsize(letter.encode("iso-8859-1"),font=self.font)
        # Create a small image to hold one character. Background is black
        charImg = Image.new('RGB', (lettersize[0], lettersize[1]))
        tmpDraw = ImageDraw.Draw(charImg)
        fill = self.getTextColor()
        tmpDraw.text((0, 0), letter.encode("iso-8859-1"),font=self.font, fill=fill)
        # Rotate a little bit, do some trick if you want
        rot = random.randint(self.letter_rotate_range[0], self.letter_rotate_range[1])
        charImg = charImg.rotate(rot, expand=1)
        return charImg


    def getLines(self, draw, image):
        """
            draw random lines
        """
        if self.enable_random_line_color or self.enable_fixed_line_color:
            r = random.Random()
            for a in range(len(self.email.encode("iso-8859-1"))):
                fill = self.getLineColor()
                x1 = r.randint(0, image.size[0])
                y1 = r.randint(0, image.size[1])
                x2 = r.randint(0, image.size[0])
                y2 = r.randint(0, image.size[1])
                width = r.randint(1, 7)
                draw.line((x1, y1, x2, y2),fill=fill, width=width)

        return draw


    def getTextColor(self):
        """
            Return a random 3-tuple for text-color
        """
        fill = random.randint(self.letter_color_red[0],
                              self.letter_color_red[1]),\
               random.randint(self.letter_color_green[0],
                              self.letter_color_green[1]),\
               random.randint(self.letter_color_blue[0],
                              self.letter_color_blue[1])
        return fill

        
    def render(self):
        
        self.getFont()
        self.email = decodeSpamSafeEmail( self.email )

        self.getImagePath()
        html = []              
        try:
            im = Image.new( "RGBA", ( 1, 1 ), ( 0, 0, 0 ) )
            
            draw = ImageDraw.Draw( im )
            textsize = draw.textsize( self.email.encode( "iso-8859-1" ),
                                     font = self.font )
            
            heigh = int( textsize[1] + 20 )
            width = int( textsize[0] * 1.6 )
            
            fill = self.getBGColor()
            
            image = Image.new( "RGB", ( width, heigh ), fill )
            
            draw = ImageDraw.Draw( image )

            ## lines behind the text
            if (self.enable_random_line_color or self.enable_fixed_line_color)\
            and self.enable_lines_in_bg:
                draw = self.getLines(draw, image)

            newtextsize = 0
            r = random.Random()

            
            imgH = self.getSpace()
            hpos = self.getSpace()
            
            for letter in self.email:
                
                charImg = self.getLetterImage( letter)
            
                # Create a mask which is same size of the small image
                mask = Image.new('L',(charImg.size[0],charImg.size[1]))
                
                mask.paste(charImg,(0,0))
            
                # Generate Random Y
                vpos = random.randint(0,20)
            
                # Paste for the visibility
                image.paste(charImg,(hpos,vpos),mask)

                if charImg.size[1] > imgH:
                    imgH = charImg.size[1]
                
                # Generate Random X
                hpos = hpos + charImg.size[0] + random.randint(self.space[0],
                                                               self.space[1])
            
            # Draw random lines in front of the image
            if (self.enable_random_line_color or self.enable_fixed_line_color)\
            and self.enable_lines_in_font:
                draw = self.getLines(draw, image)
                          
            del draw
            
            html.append(u"""<table><tbody><tr><td style="border: 0pt none ;text-align: center;">""")
            if self.enable_split_image and type(self.entrys) == int and self.entrys:
                hpos = 0
                for entry in range(self.entrys):
                    width = int(image.size[0]/self.entrys)
                    im = Image.new( "RGB",(width,image.size[1] ) )
                    im.paste(image,(0-hpos,0))
                    hpos += width
                    imagename =  self.imgname + "_" + str(entry)  + ".jpg" 
                    im.save(self.imgpath  + "/" + imagename, "JPEG")
                    html.append( self.getHTML( imagename ) )
            else:
                imagename =  self.imgname + "_0.jpg" 
                image.save(self.imgpath  + "/" + imagename, "JPEG")
                html.append( self.getHTML( imagename ) )
                
        
            html.append( u"""</td></tr><tr><td style="border: 0pt none ;text-align: center;">""")
            html.append( u"""<a href="?action=show">%(refresh_text)s</a> """
                         % { u"refresh_text" : self.refesh_text })
            html.append( u"""</td></tr></tbody></table>""")
        except:
            pass
        
        return "\n".join(html)
    
    def getLineColor(self):
        """
            Return a random 3-tuple for line-color
        """
        r = random.Random()
        try:
            if self.enable_fixed_line_color:
                # get defined color
                return self.line_color_fixed
            elif self.enable_random_line_color:
                # generate random color
                return (r.randint(self.line_color_red[0],self.line_color_red[1]),r.randint(self.line_color_green[0],self.line_color_green[1]),r.randint(self.line_color_blue[0],self.line_color_blue[1]))
            else:
                return ( 0, 0, 0 )
        except:
            return ( 0, 0, 0 )
    
    def getBGColor(self):
        """
            Return a random 3-tuple for background-color
        """
        r = random.Random()
        if self.enable_fixed_bg_color:
            return self.bg_color_fixed
        elif self.enable_random_bg_color:
            return (r.randint(self.bg_color_red[0],self.bg_color_red[1]),r.randint(self.bg_color_green[0],self.bg_color_green[1]),r.randint(self.bg_color_blue[0],self.bg_color_blue[1]))
        else:
            return 256,256,256
        
    def getHTML(self, imagename):
        """
            Create the HTML for the page
        """
        kw = {} 
        kw['src'] = AttachFile.getAttachUrl(self.pagename,
                                            imagename.encode("iso-8859-1"),
                                            self.request)

        html = []
 
        if self.javascript_enable:
            html.append( u"""\n<script language="JavaScript"><!--\n""")
            index = 0
            for char in self.email:
                html.append( u"""var v%(index)d = "%(char)s";\n"""
                             % { u"index" : index, u"char" : char } )
                index += 1
            html.append( u"""document.write('<a href=\"mailto:'""")
            
            for index in range(len(self.email)):
                html.append( u""" + v%d""" % index )
             
            html.append( u""" + '\">');""")
            
            html.append( u"""document.write('""")
#                     
        html.append( self.formatter.image( **kw ) )
        
        if self.javascript_enable:
            html.append(u"""</a>');""")
            
            html.append( u"""// --></script>\n""")
        
        return u"".join(html)

    def getImagePath(self):
        """
            return path to save the new image
        """
        self.getImageName()
        self.imgpath = AttachFile.getAttachDir(self.request,self.pagename,
                                               create=1)

    def getFontPath(self):
        self.getFontDir()
        self.font_file =  self.font_dir + '\\' + self.font

    def getFont(self):
        """
            create the font opject
        """
        self.getFontPath()
        try:
            self.font  = ImageFont.load(self.font_file)
        except:
            self.font = None
        
    def getImageName(self):
        """
            return the crypted imagename
        """
        import base64
        
        filename = self.email.encode("utf-8")
        filename = sha.new(filename).hexdigest()
        filename = base64.encodestring(filename).rstrip()
        self.imgname = "cryptedemail_" + filename
        
    def getFontDir(self):
        """
            return the directory of the font
        """
        try:
            self.font_dir = self.request.cfg.font_dir
        except:
            self.font_dir = self.request.cfg.plugin_dir + "\\font"

def execute(macro, args):
    return UserList(macro, args).render()
