#
#       Copyright (C) 2014
#       Sean Poyser (seanpoyser@gmail.com)
#
#  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 2, 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 General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with XBMC; see the file COPYING.  If not, write to
#  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#  http://www.gnu.org/copyleft/gpl.html
#

import urllib
import os
import sfile
import dixie

DSF = dixie.isDSF()


def tidy(text):
    if isinstance(text, bool):
        return '1' if text else '0'

    if (not isinstance(text, unicode)) and (not isinstance(text, str)):
        text = str(text)
    text = text.replace('\n', '')
    text = text.replace('\r', '')
    text = text.replace('\\', '/')
    return text
    


class Channel(object):
    def __init__(self, id, title='', logo='', streamUrl='', visible=1, weight=-1, categories='', userDef=0, desc='', isClone=0, isFave=0, offset=0):
        if isinstance(id, list):
            self.setFromList(id)
        else:
            self.set(id, title, logo, streamUrl, visible, weight, categories, userDef, desc, isClone, isFave, offset)


    def set(self, id, title, logo, streamUrl, visible, weight, categories, userDef, desc, isClone, isFave, offset):
        if logo:
            logo = tidy(logo)

        self.id         = tidy(id)
        self.title      = tidy(title)
        self.categories = tidy(categories)
        self.logo       = logo
        self.streamUrl  = tidy(streamUrl)

        self.visible = int(tidy(visible))
        self.weight  = int(tidy(weight))
        self.userDef = int(tidy(userDef))
        self.isClone = int(tidy(isClone))

        try:     self.isFave = int(tidy(isFave))
        except:  self.isFave = 0

        try:     self.offset = int(tidy(offset))
        except:  self.offset = 0

        self.desc = tidy(desc)

        if DSF:
            self.title = urllib.unquote_plus(self.title)

    def isProtected(self):
        return dixie.ADULT in self.categories


    def setFromList(self, list):
        userDef = False
        isClone = False
        isFave  = False
        offset  = 0
        desc    = ''

        if len(list) > 7:
            userDef = list[7]

        if len(list) > 8:
            desc = list[8]

        if len(list) > 9:
            isClone = list[9]
        
        if len(list) > 10:
            isFave = list[10]

        if len(list) > 11:
            offset = list[11]


        self.set(list[0], list[1], list[2], list[3], list[4], list[5], list[6], userDef, desc, isClone, isFave, offset)


    def safeWriteToFile(self, file, text):
        if text:
            try:    file.write(text.encode('utf8'))
            except: file.write(text)

        file.write('\n')


    def writeToFile(self, filename):
        cloneID = -1
        localID = self.id

        if self.isClone:
            filename, cloneID = self.cloneFilename(filename)
            localID += cloneID

        try:    f = sfile.file(filename, 'w')
        except: return False

        self.safeWriteToFile(f, localID)
        self.safeWriteToFile(f, self.title)
        self.safeWriteToFile(f, self.logo)
        self.safeWriteToFile(f, self.streamUrl)

        if self.visible:
            f.write('1\n')
        else:
            f.write('0\n')

        f.write(str(self.weight) + '\n')

        self.safeWriteToFile(f, self.categories)

        if self.userDef:
            f.write('1\n')
        else:
            f.write('0\n')

        self.safeWriteToFile(f, self.desc)

        if self.isClone:
            f.write('1\n')
        else:
            f.write('0\n')

        if self.isFave:
            f.write('1\n')
        else:
            f.write('0\n')

        f.write(str(self.offset) + '\n')

        f.close()
        return True


    def cloneFilename(self, filename):
        if '_clone_' in filename:
            return filename, ''

        index    = 1
        root     = filename
        filename = root + '_clone_%d' % index

        while sfile.exists(filename):
            index += 1
            filename = root + '_clone_%d' % index

        return filename, '_clone_%d' % index


    def clone(self):
        c = Channel(self.id, self.title, self.logo, self.streamUrl, self.visible, self.weight, self.categories, self.userDef, self.desc, self.isClone, self.isFave, self.offset)
        return c


    def compare(self, channel):
        if self.visible != channel.visible:
            return False

        if self.weight != channel.weight:
            return False

        if self.title != channel.title:
            return False

        if self.logo != channel.logo:
            return False

        if self.categories != channel.categories:
           return False

        if self.isFave != channel.isFave:
           return False

        if self.offset != channel.offset:
           return False

        return True


    def __eq__(self, other):
        if not hasattr(self, 'id'):
            return False

        if not hasattr(other, 'id'):
            return False

        return self.id == other.id


    def __repr__(self):
        try:
            return 'Channel(id=%s, title=%s, categories=%s, logo=%s, streamUrl=%s, weight=%s, visible=%s userDef=%s desc=%s isClone=%s isFave=%s, offset=%s)' \
               % (self.id, self.title, self.categories, self.logo, self.streamUrl, str(self.weight), str(self.visible), str(self.userDef), self.desc, str(self.isClone), str(self.isFave), str(self.offset))
        except:
            return 'Can\'t display channel'


    def getWeight(self):
        return self.weight


#############################################################


def GetChannelFromFile(filename):
    try:    return Channel(sfile.readlines(filename))
    except: return None


def _ConfirmUpdate(folder):
    dixie.log('==== Confirm Update ====')
    src = os.path.join(folder, 'tempchannels')
    dst = os.path.join(folder, 'channels')

    dixie.log('==== src/dst ====')
    dixie.log(src)
    dixie.log(dst)
    CheckForNewChannels(src)

    newFiles = []

    current, dirs, files = sfile.walk(src)
    for file in files:
        filename = os.path.join(dst, file)
        if not sfile.exists(filename):
            newFiles.append(file)

    if len(newFiles) == 0:
        return

    channels = []
    titles   = ['[I]All Channels[/I]']

    for file in newFiles:
        channel = GetChannelFromFile(os.path.join(src, file))
        if channel:
            channels.append(channel)
            titles.append(channel.title)

    import xbmcgui

    selections = xbmcgui.Dialog().multiselect('New channels detected - please choose those you wish to add', titles)

    if not selections:
        selections = []

    addAll = 0 in selections

    for idx, channel in enumerate(channels):
        visible = addAll
        if idx+1 in selections: # +1 to account for 'All Channels' item
            visible = True

        channel.visible = visible
        channel.writeToFile(os.path.join(dst, newFiles[idx]))

    sfile.rmtree(src)


def ConfirmUpdate(folder):
    try:
        return _ConfirmUpdate(folder)
    except Exception, e:
        dixie.DialogOK(str(e))
        dixie.log('Error %s in Channel.ConfirmUpdate' % str(e))


def CheckForNewChannels(src):
    dixie.log('==== Check For New Channels ====')
    if not os.path.exists(src):
        sfile.makedirs(src)

    logoFolder = dixie.GetLogoFolder() # Get the logo folder setting.
    if dixie.GetSetting('logo.type') == '1':
        logoPath = logoFolder
    else:
        logoPath = 'special://profile/addon_data/script.tvguidedixie/extras/logos/' + logoFolder + '/'

    newChannelList = dixie.loadChannelList() # Read channels.json and return a list. File is downloaded in DB.zip.
    oldChannelList = dixie.getAllChannels()  # Read files in existing channels folder and return a list

    newChannels   = []
    oldChannels   = []
    oldCategories = []

    for oldChannel in oldChannelList:
        oldChannelTitle = oldChannel[2].title
        oldChannels.append(oldChannelTitle)

        oldChannelCats  = oldChannel[2].categories.split('|')

        for category in oldChannelCats:
            if category not in oldCategories:
                oldCategories.append(category)

    # dixie.log('==== oldChannels ====')
    # dixie.log(oldChannels)
    # dixie.log('==== oldCategories ====')
    # dixie.log(oldCategories)

    for newIdx, newChannel in enumerate(newChannelList):
        newIdx      = newIdx+1
        id          = newChannel[0]
        title       = newChannel[1]

        defaultcats = newChannel[2]

        try:
            lineupcats  = newChannel[3].split('|')
        except:
            lineupcats  = ''

        # dixie.log('=========== CH TITLE ===========')
        # dixie.log(title)
        categories = checkCategories(oldCategories, defaultcats, lineupcats)

        logo = logoPath + title + '.png'

        if title not in oldChannels:
            channelToAdd   = Channel(id, title, weight=newIdx, logo=logo, categories=categories)
            newChannelItem = [newIdx, id, channelToAdd]
            newChannels.append(newChannelItem)

    for item in newChannels:
        ch   = item[2]
        chID = item[1]
        ch.writeToFile(os.path.join(src, dixie.CleanFilename(chID)))


def checkCategories(oldCategories, defaultcats, lineupcats):
    # dixie.log('=========== defaultcats ===========')
    # dixie.log(defaultcats)
    # dixie.log('=========== lineupcats ===========')
    # dixie.log(lineupcats)

    for category in oldCategories:
        if not category == 'uncategorised':
            catname = category.split('. ')[-1]

            for lineupcat in lineupcats:
                if lineupcat == catname:
                    # dixie.log('=========== MATCH ===========')
                    # dixie.log(lineupcat)
                    # dixie.log(catname)
                    # dixie.log(category)
                    return category

    # dixie.log('=========== NO MATCH ===========')
    # dixie.log(defaultcats)
    return defaultcats

