#! /usr/bin/python
# -*- coding: utf-8 -*-

"""
Copyright (C) 2016 Borja Menendez Moreno

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
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 General Public License for more details.

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

Authors: Borja Menéndez Moreno <info20up@gmail.com>

This is the API Wrapper for the 20up backup program. This wrapper allows
a client to retrieve information about his specific account.
"""

import os, urllib, string
from time import sleep
from tntapi import *

CONSTANT_FILL = 6
MAX_TRIES = 10
ROOTPATH = os.getcwdu()
PHOTOS = 'fotos'
COMMENTS = 'comentarios'
JPG = '.jpg'
TXT = '.txt'

def getFullName(picture, counter):
    return normalize(string.zfill(counter, CONSTANT_FILL) + '_' + picture[2] + '_' + picture[1])

class Wrapper():
    """
    The wrapper for the tntapi.
    This class eases the connection.

    When constructed, it raises a RuntimeError if it is impossible to log in the
    social network.
    """
    def __init__(self, browser, console=False):
        self.tnt = API(browser)
        self.isLogged = False
        self.console = console
        
    def waitForLogin(self):
        self.tnt.waitForLogin()
            
    def downloadPicturesFromAlbum(self, album, totalPictures, alreadyDownloaded, oldFirstPicture, comments=False):
        """
        Download pictures from a given album into the given directory.

        Args:
            album: the album.
            totalPictures: the total number of pictures of the user.
            alreadyDownloaded: the number of pictures already downloaded.
            oldFirstPicture: the first picture of the previous album.
            comments: indicates wether obtain comments of the picture or not.

        Raises:
            RuntimeError if the user is not already logged in.
        """
        if not self.isLogged:
            raise RuntimeError('Es necesario estar logueado en la red social')
            
        if self.console:
            print '|'
            print '| Album', album[0]
            print '|'
            print '| Obteniendo informacion del album'

        joinPath = os.path.join(ROOTPATH, PHOTOS)
        if not os.path.exists(joinPath):
            if self.console:
                print '| Creando directorio donde se alojaran todas las fotos...'
            os.makedirs(joinPath)
            if self.console:
                print '| Directorio creado'
                
        albumPath = os.path.join(joinPath, album[0])
        if not os.path.exists(albumPath):
            if self.console:
                print '| Creando directorio donde se alojaran las fotos del album...'
            os.makedirs(albumPath)
            if self.console:
                print '| Directorio creado'
        os.chdir(albumPath)

        if self.console:
            print '| Comenzando la descarga de las fotos del album...'
            
        counter = 1
        newFirstPicture = self.tnt.getFirstPicture(album[2], oldFirstPicture)
        firstPicture = ''
        lastPicture = ['']
        oldSrc = ''
        while counter <= album[1] and newFirstPicture != oldFirstPicture:
            pic = self.tnt.getPicture(oldSrc, comments)
            oldSrc = pic
            if counter == 1:
                firstPicture = pic
            elif pic[0] == firstPicture[0]:
                break
            if lastPicture[0] != pic[0]:
                self.savePicture(pic, counter, album[1], totalPictures, alreadyDownloaded + counter)
                if comments:
                    self.saveComments(pic, counter)
                counter += 1
                lastPicture = pic
            self.tnt.getNextPicture()
            
        return newFirstPicture
            
    def savePicture(self, picture, myCounter, totalAlbum, totalPics, alreadyDown):
        """
        Save a picture.

        Args:
            picture: a picture to be saved.
            myCounter: the counter for the picture.
            totalAlbum: the number of pictures of the album.
            totalPics: the number of pictures of the user.
            alreadyDown: the number of pictures already downloaded.
        """
        sleep(0.25)
        picName = getFullName(picture, myCounter) + JPG
        if not os.path.exists(picName):
            if self.console:
                totalPerc = str(100 * alreadyDown / totalPics)
                albumPerc = str(100 * myCounter / totalAlbum)
                print '|'
                print '| [' + totalPerc + '% total] [' + albumPerc + '% album]'
                print '| Descargando foto ' + picName + '...'
            urllib.urlretrieve(picture[0], picName)
            
    def saveComments(self, picture, myCounter):
        """
        Save a picture's comments.
        
        Args:
            picture: to obtain the comments.
            myCounter: to know the name of the file with comments.
        """
        commentsFileName = getFullName(picture, myCounter) + TXT
        if not os.path.exists(commentsFileName) and picture[3] != []:
            if self.console:
                print '| Descargando sus comentarios...'
            file2write = open(commentsFileName, 'w')
            for comment in picture[3]:
                file2write.write('******************\r\n')
                file2write.write(comment.encode('utf-8') + '\r\n')
            file2write.close()

    def downloadAllPictures(self, comments=False):
        """
        Download all the pictures for all the albums.

        Args:
            comments: indicates wether obtain comments of the picture or not.

        Raises:
            RuntimeError if the user is not already logged in.
        """
        allAlbums = self.tnt.getAllAlbums()
        self.isLogged = (allAlbums != None)
        if not self.isLogged:
            return -1
            
        totalPictures = 0
        for album in allAlbums:
            totalPictures += album[1]
            
        alreadyDownloaded = 0
        oldFirstPicture = ''
        for album in allAlbums:
            oldFirstPicture = self.downloadPicturesFromAlbum(album, totalPictures, alreadyDownloaded, oldFirstPicture, comments)
            alreadyDownloaded += album[1]
            
        return 0
        
    def goToPrivates(self):
        """
        Call the API to go to the private messages' page.
        """
        self.tnt.goToPrivates()
        
    def downloadAllComments(self):
        """
        Download all the comments in the wall.
        """
        os.chdir(ROOTPATH)
        file2write = open(COMMENTS + TXT, 'w')
        
        tries = 0
        discard = 0
        while True:
            comments = self.tnt.loadMoreComments(discard)
            if not comments:
                if tries < MAX_TRIES:
                    tries += 1
                    sleep(0.3)
                else:
                    break
            else:
                tries = 1
                discard += len(comments)
                if self.console:
                    print '| Descargados ', discard, 'comentarios'
                self.saveWall(comments, file2write)
        file2write.close()
            
    def saveWall(self, comments, file2write):
        """
        Write the comments in the file.
        
        Args:
            comments: the list of comments to be saved.
            file2write: the file to write in.
        """
        for comment in comments:
            file2write.write(comment.encode('utf-8') + '\r\n\r\n')