class Kraska:
    token = False

    def __init__(self, u=None, p=None):
        self.username = u if u is not None else settings.get_setting('kraska.user')
        self.password = p if p is not None else settings.get_setting('kraska.pass')

    def login(self):
        try:
            debug('kra login start ****/****'.format(self.username, self.password))
            data = self.get_data('/api/user/login', {'data': {'username': self.username, 'password': self.password}})
            if "session_id" in data:
                debug('kra login OK')
                self.set_token(data.get('session_id'))
                return True
        except:
            debug('kra err login: {}'.format(traceback.format_exc()))
            data = {}
            pass
        self.set_token(False)
        debug('DATA: {}'.format(data))
        debug('kra login FALSE')
        return False

    def set_token(self, token):
        if token != self.token:
            self.token = token
            debug('kra set token: {}'.format(str(token)))
            checksum_credentials = self._get_chsum(self.username, self.password)
            settings.set_setting('kraska.chsum', '{}'.format(checksum_credentials))
            settings.set_setting('kraska.token', '{}'.format(token))
            debug('kra set chsum: {}'.format(checksum_credentials))

    @staticmethod
    def _get_chsum(username, password):
        return md5(
            "{}|{}".format(password.encode('utf-8'),
                           username.encode('utf-8')).encode('utf-8')).hexdigest()

    def get_token(self):
        # debug('get_token start')
        try:
            chsum = settings.get_setting('kraska.chsum')
            if chsum is None or chsum == '':
                self.token = False
                return False
            testchsum = self._get_chsum(self.username, self.password)
            debug('chsum [{}] vs [{}]'.format(chsum, testchsum))
            if chsum != testchsum:
                debug('prihlasovacie udaje niesu zhodne s tokenom, treba login')
                self.token = False
                return False
        except Exception as e:
            debug('error get token: {}'.format(traceback.format_exc()))
            self.token = False
            return False
        # debug('get_token from settings')
        token = settings.get_setting('kraska.token')
        if token == '' or 'False' == token or None is token:
            token = False
        self.token = token
        # debug('get_token: {}'.format(token))
        return token

    def resolve(self, ident):
        # debug('kra resolve: {} token: {}'.format(ident, self.get_token()))
        if self.get_token() is False:
            debug('nemame token v resolve a nepodarilo sa nam ani prihlasit')
            if self.login() is False:
                self.wrong_credential()
                return None

        debug('ideme na zostavajuce dni')
        try:
            days_left = self.get_days_left()
            if days_left is None:
                raise Exception
        except:
            dok(Strings.txt(Strings.RESOLVE_ERROR_H1), Strings.txt(Strings.KRASKA_NOTIFY_NO_SUBSCRIPTION))
            return None

        if 14 >= days_left:
            debug('mame nizky pocet dni predplatneho')
            dnotify(Strings.txt(Strings.KRASKA_NOTIFY_LOW_DAYS_LEFT).format(days_left), '')
        try:
            debug('skusame resolvnut ident: {}'.format(ident))
            data = self.get_data('/api/file/download', {"data": {"ident": ident}})
            if "data" in data and "link" in data.get("data", {}):
                debug('kra resolvovala {}'.format(data.get("data").get("link")))
                return data.get("data").get("link")
            debug('Nepodarilo sa resolvnut subor: {}'.format(ident))
        finally:
            pass
        debug('kra resolve error')
        raise ResolveException("Chybny subor")

    def get_days_left(self):
        debug('get days left')
        user_info = self.user_info()
        if user_info is None or user_info is False:
            debug('nepodarilo sa natiahnut info o userovi')
            self.set_token(False)
            raise ResolveException("User nieje prihlaseny")

        if user_info.get('subscribed_until', None) is None:
            debug('user nema aktivne predplatne')
            raise ResolveException("Nieje predplatne")

        debug('idem vratit pocet dni {}'.format(user_info))
        return user_info.get('days_left', 0)

    def get_data(self, endpoint, data=None):
        if data is None:
            data = {}
        if self.token:
            data.update({'session_id': self.token})
        debug('kra req: {}'.format(endpoint, json.dumps(data)))
        try:
            raw_data = Http.post(BASE + endpoint, json=data)
            # debug('kra raw response: {}'.format(raw_data.text))
            return raw_data.json()
        except Exception as e:
            return False

    def user_info(self, level=0):
        debug('skusam natiahnut user info')
        if self.get_token() is False:
            if self.login() is False:
                debug('Nepodarilo sa ziskat info o userovi, lebo nieje prihlaseny')
                return False
        debug('mame token/sme uz prihlaseny')
        try:
            data = self.get_data('/api/user/info')
            if data is False or 'data' not in data:
                debug('mame error na info {}'.format(data))
                raise Exception(data.get('msg', 'kraska error'))
            days_left = data.get('data', {}).get('days_left', 0)
            days_left = 0 if days_left is None else days_left
            settings.set_setting('kraska.days.left', days_left)
            debug('vracame info o userovi {}'.format(data.get('data', False)))
            return data.get('data', False)
        except Exception as e:
            debug('kra erro: {}'.format(traceback.format_exc()))
            self.set_token(False)
            if level == 0:
                debug('skusame znova natiahnut info o userovi')
                return self.user_info(1)
        debug('vzdali sme info o userovi ... nieje prihlaseny')
        return False

    def check_user(self):
        debug('check_user start')
        if settings.get_setting('kraska.user'):
            try:
                if not self.user_info():
                    raise Exception()
            except:
                self.wrong_credential()
                return

            try:
                self.get_days_left()
            except:
                dok('{} - {}'.format(Strings.txt(Strings.RESOLVE_ERROR_H1), ADDON.getAddonInfo('name')), Strings.txt(Strings.KRASKA_NOTIFY_NO_SUBSCRIPTION))

    def wrong_credential(self):
        res = dyesno('{} - {}'.format(Strings.txt(Strings.KRASKA_NOTIFY_CREDENTIAL_H1), ADDON.getAddonInfo('name')),
                     Strings.txt(Strings.KRASKA_NOTIFY_CREDENTIAL_L1))
        if res:
            open_settings('0.0') class AndroidTv(KodiDb):
    def __init__(self):
        KodiDb.__init__(self)
        self.list = List('android')
        self.last_run = 0

    def cleanup_library_path(self, path):
        sql = "" \
              "select " \
              "     'path' as typ, " \
              "     'idPath' as field, " \
              "      idPath as id " \
              "from " \
              "     path " \
              "where " \
              "     idparentpath in (" \
              "         select " \
              "             idpath " \
              "         from " \
              "             path " \
              "         where " \
              "             strpath=?" \
              "     ) " \
              "union all " \
              "select " \
              "     'files' as typ, " \
              "     'idFile' as field, " \
              "     idfile as id " \
              "from " \
              "     files " \
              "where " \
              "     idpath in (" \
              "         select " \
              "             idpath " \
              "         from " \
              "             path " \
              "         where " \
              "             idparentpath in (" \
              "                 select " \
              "                     idpath " \
              "                 from " \
              "                     path " \
              "                 where " \
              "                     strpath=?" \
              "             )" \
              "     ) " \
              "union all " \
              "select " \
              "     'movie' as typ, " \
              "     'idMovie' as field, " \
              "     idmovie as id " \
              "from " \
              "     movie " \
              "where " \
              "     idfile in (" \
              "         select " \
              "             idfile as id " \
              "         from " \
              "             files " \
              "         where " \
              "             idpath in (" \
              "                 select " \
              "                     idpath " \
              "                 from " \
              "                     path " \
              "                 where " \
              "                     idparentpath in (" \
              "                         select " \
              "                             idpath " \
              "                         from " \
              "                             path " \
              "                         where " \
              "                             strpath=?" \
              "                     )" \
              "             )" \
              "     )"
        res = self._db.execute(sql, path, path, path).fetchall()
        for i in res:
            debug('{}'.format(i))
            sql = 'delete from {} where {}=?'.format(i[0], i[1])
            debug('SQL: {}'.format(sql))
            self._db.execute(sql, i[2])
        return True

    def get(self, url):
        pass

    def run(self):
        path = get_setting('androidtv.path')
        cur = int(time())
        if path and self.last_run + 3600 < cur:
            self.last_run = time()
            items = self.list.get()
            for i in items:
                path_name = make_legal_filename('{}/{}/'.format(path, i.get(SC.ITEM_ID)))
                debug('android: {} {}'.format(i, path_name))
                mkdir(path_name)
                files = xbmcvfs.listdir(path_name)
                debug('files {}'.format(files))
                for f in files:
                    if len(f):
                        debug('file: {}'.format(f))
                        xbmcvfs.delete(f[0])
                res = Sc.get(i.get('url'))
                menu = res.get('menu', {})
                if len(menu):
                    debug('Mame menu polozky')
                    for pos, s in enumerate(menu):
                        if pos < 30:
                            url = create_plugin_url({
                                SC.ITEM_ID: '{}'.format(s.get('id', 0)),
                                SC.ITEM_URL: s.get('url', '')
                            })
                            base_name = '{}{:04d}'.format(path_name, pos)
                            fn = make_legal_filename('{}.strm'.format(base_name))
                            # debug('{} -> {} {} {}'.format(pos, fn, url, s.get(SC.ITEM_UIDS)))
                            fs = xbmcvfs.File(fn, 'w')
                            fs.write('{}'.format(url))
                            fs.close()
                            nfo = SCNFO(s)
                            # debug('NFO: {}'.format(encode(nfo.xml())))
                            fs = xbmcvfs.File(make_legal_filename('{}.nfo'.format(base_name)), 'w')
                            fs.write('{}'.format(encode(nfo.xml())))
                            fs.close()
                playlist_base = make_legal_filename('special://profile/playlists/video/')
                xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>' \
                      '<smartplaylist type="movies">' \
                      ' <name>{}</name>' \
                      ' <match>all</match>' \
                      ' <rule field="path" operator="contains"><value>{}</value></rule>' \
                      '</smartplaylist>'
                xbmcvfs.mkdirs(playlist_base)
                filename = make_legal_filename('{}{}.xsp'.format(playlist_base, i.get(SC.ITEM_ID)))
                fs = xbmcvfs.File(filename, 'w')
                fs.write(xml.format(i.get(SC.ITEM_ID), path_name))
                fs.close()
            self.cleanup_library_path(path)
            exec_build_in('UpdateLibrary(video,{})'.format(path)) def debug(text):
    xbmc.log('[{}] {}'.format(APP, text), xbmc.LOGDEBUG) ADDON = xbmcaddon.Addon(id=ADDON_ID) ADDON_ID = 'plugin.video.stream-cinema' def dtextviewer(heading, text):
    dialog().textviewer(heading, text) def sleep(sleep_time):
    mon = xbmc.Monitor()
    while not mon.abortRequested() and sleep_time > 0:
        sleep_time -= 100
        xbmc.sleep(99) def set_setting(key, val):
    debug('set_settings {} {}'.format(key, val))
    return addon.setSetting(key, '{}'.format(val)) def get_uuid():
    # pylint: disable=global-statement
    global __CRYPT_KEY__
    if not __CRYPT_KEY__:
        __CRYPT_KEY__ = _get_system_uuid()
    return __CRYPT_KEY__ def get_setting(key):
    return addon.getSetting(key) def exec_build_in(cmd):
    cmd = cmd.replace('__self__', ADDON_ID)
    debug('exec {}'.format(cmd))
    xbmc.executebuiltin(cmd) def get_setting_as_bool(key):
    try:
        return addon.getSettingBool(key)
    except:
        return get_setting(key) == 'True' or get_setting(key) == 'true' def update_addon():
    from resources.lib.common.storage import KodiAddonsDb
    set_general_addonupdates(0)
    set_update_addons(1)

    addon_db = KodiAddonsDb()
    addon_db.enable_auto_update()
    exec_build_in('UpdateAddonRepos')
    exec_build_in("UpdateLocalAddons") def clean_textures():
    try:
        from resources.lib.common.storage import TexturesDb
        t = TexturesDb()
        t.clean()
    except:
        debug('player err: {}'.format(traceback.format_exc())) class SCDispatcher:
class SSLSCDispatcher:
class SCWebSocketApp(websocket.WebSocketApp):
class WS(Monitor):
    def __init__(self, app, ping_timeout):
    def read(self, sock, read_callback, check_callback):
    def __init__(self, app, ping_timeout):
    def read(self, sock, read_callback, check_callback):
    def select(self):
    def __init__(self, url, header=None,
                 on_open=None, on_message=None, on_error=None,
                 on_close=None, on_ping=None, on_pong=None,
                 on_cont_message=None,
                 keep_running=True, get_mask_key=None, cookie=None,
                 subprotocols=None,
                 on_data=None):
    def create_dispatcher(self, ping_timeout):
    def __init__(self):
    def run(self):
    def run_ws(self):
    def onNotification(self, sender, method, data):
    def reconnect(self):
    def on_message(self, message): class Monitor(KMonitor):
    SORT_ASC = 1
    SORT_DESC = 2
    SORT_METHOD_NONE = 0
    SORT_METHOD_RATING = 17
    SORT_METHOD_MPAA = 31
    SORT_METHOD_TITLE = 29
    SORT_METHOD_YEAR = 16
    SORT_METHOD_DATE_ADDED = 40
    def __init__(self):
    def onSettingsChanged(self):
    def onScreensaverActivated(self):
    def onScreensaverDeactivated(self):
    def onDPMSActivated(self):
    def onDPMSDeactivated(self):
    def onScanStarted(self, library):
    def onScanFinished(self, library):
    def onCleanStarted(self, library):
    def onCleanFinished(self, library):
    def onSleep(self, data):
    def onWake(self, data):
    def PlayerOnAVStart(self, data):
    def onNotification(self, sender, method, data):
    def periodical_check(self):
    def can_check(self): class SCPlayer(Player):
    def __init__(self):
    def onPlayBackStarted(self):
    def set_item(self, item=None):
    def try_audio(self, lang, streams):
    def onAVStarted(self):
    def onAVChange(self):
    def onPlayBackEnded(self):
    def onPlayBackStopped(self):
    def onPlayBackError(self):
    def onPlayBackPaused(self):
    def onPlayBackResumed(self):
    def onQueueNextItem(self):
    def onPlayBackSpeedChanged(self, speed):
    def onPlayBackSeek(self, time, seekOffset):
    def onPlayBackSeekChapter(self, chapter):
    def clean(self):
    def end_playback(self):
    def percent_played(self):
    def set_watched(self):
    def check_up_next(self, percent_played):
    def send_up_next(self):
    def run(self):
    def getTime1(self):  # type: () -> float
    def isPlayingVideo1(self):  # type: () -> bool
    def periodical_check(self):
    def isPlayback(self):  # type: () -> bool class NextEp:

    def __init__(self):
        self.list = Storage('nextep')
        # dal som to sem natvrdo, aby sa oneskoril sync o 10 minut po starte
        last_run = settings.get_setting_as_int('system.next_ep.last_run')
        if last_run is None:
            self.last_run = time()
        else:
            self.last_run = last_run

    def run(self, force=False):
        now = time()
        if not player.isPlayback() and (force or self.last_run + (3600 * 3) < now):
            if self.update_items():
                self.last_run = now
                settings.set_setting('system.next_ep.last_run', '{}'.format(int(now)))

    def update_items(self):
        query = 'select item_key, item_value from storage where item_key like ? and item_value like ?'
        search = '{}-%'.format(SCKODIItem.ITEM_NAME)
        # debug('search: {}'.format(search))
        res = self.list._db.execute(query, search, '%"last_ep"%').fetchall()
        total = len(res)
        skip_list = self.get()
        debug('NEXTEP: {} z {} ({})'.format(len(skip_list), total, total - len(skip_list)))
        dialog = dprogressgb()
        dialog.create('Next Ep in progress')
        pos = 0
        for i in res:
            if monitor.abortRequested() or player.isPlayback():
                dialog.close()
                return False
            pos += 1
            _, item_id = i[0].split('-')
            if item_id in skip_list:
                debug('ITEM {} uz ma nextep, nepotrebujeme update'.format(item_id))
                continue
            item = SCKODIItem(item_id)
            last_ep = item.get_last_ep()
            debug('Next Ep in progress: {}%'.format(int(pos / total * 100)))
            dialog.update(int(pos / total * 100), message='{} - {}x{}'.format(item_id, last_ep[0], last_ep[1]))
            try:
                debug('last {}x{}'.format(last_ep[0], last_ep[1]))
                info = Sc.up_next(item_id, last_ep[0], last_ep[1])
                if 'error' in info or ('info' in info and info.get('info') is None):
                    debug('nemame data k next EP')
                    continue
                new = {
                    's': last_ep[0],
                    'e': last_ep[1],
                    't': int(time()),
                }
                cur = self.list.get(item_id)
                if cur is None or (cur and str(cur.get('e')) != str(new.get('e'))):
                    debug('nextep update {} -> {}'.format(item_id, last_ep))
                    self.list[item_id] = new
                else:
                    debug('nezmenene {} -> {}'.format(item_id, last_ep))
            except:
                debug('mazem serial zo zoznamu {}'.format(item_id))
                del(self.list[item_id])
                pass

        dialog.close()
        debug('LIST NEXT EP: {}'.format(self.list._data))
        return True

    def get(self):
        tmp = {}
        for k in self.list._data.items():
            if k[1]['t'] is not None:
                tmp.update({k[0]: k[1]})
            else:
                debug('ERR ITEM: {}'.format(k))

        debug('GET NEXT EP: {}'.format(tmp))
        ret = [k[0] for k in sorted(tmp.items(), key=lambda x: x[1]['t'], reverse=True)]
        return ret
import traceback
from resources.lib.api.kraska import Kraska
from resources.lib.common.android import AndroidTv
from resources.lib.common.logger import debug
from resources.lib.constants import ADDON, ADDON_ID
from resources.lib.gui.dialog import dtextviewer
from resources.lib.kodiutils import sleep, set_setting, get_uuid, get_setting, exec_build_in, get_setting_as_bool, \
    update_addon, clean_textures
from resources.lib.services import websocket
from resources.lib.services.Monitor import monitor
from resources.lib.services.SCPlayer import player
from resources.lib.services.next_episodes import NextEp
        from threading import Thread
                    from resources.lib.trakt.Trakt import trakt
from __future__ import print_function, unicode_literals




class Service:
    next_ep = None
    monitor = None
    player = None
    trakt = None
    atv = None

    def __init__(self):
        set_setting('system.ver', ADDON.getAddonInfo('version'))
        get_uuid()
        if get_setting('androidtv.path'):
            self.atv = AndroidTv()

    def run(self):
        debug('START SERVICE....................................................................')
        last_changelog = get_setting('system.changelog')

        update_addon()

        if last_changelog != ADDON.getAddonInfo('version'):
            debug('SYSTEM.CHANGELOG: {}'.format(ADDON.getAddonInfo('changelog')))

            set_setting('system.changelog', '{}'.format(ADDON.getAddonInfo('version')))