# -*- coding: utf-8 -*-

# Copyright © 2015 Collabora Ltd.
#
# SPDX-License-Identifier: MPL-2.0
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import subprocess
import shutil
import os

from gi.repository import GLib
from gi.repository import TrackerControl
from gi.repository import Tracker

from . import LONG_JPEG_NAME


class TrackerIndexerMixin:
    def __init__(self):
        print("TrackerIndexerMixin: Stop tracker-store and tracker-miner-fs "
              "services")
        subprocess.check_call(
            'systemctl --user stop tracker-store tracker-miner-fs',
            shell=True)

        print("TrackerIndexerMixin: Reset tracker's DB")
        subprocess.check_call('yes | tracker reset -r',
                              stdout=subprocess.DEVNULL,
                              shell=True)

        print("TrackerIndexerMixin: init done")

    def miner_progress_cb(self, manager, miner, status, progress,
                          remaining_time):
        # Ignore signal if status didn't change
        if self.statuses[miner] == status:
            return

        print("TrackerIndexer: Miner '%s' status changed to '%s'" %
              (miner, status))
        self.statuses[miner] = status

        # We are only interested about miners becoming Idle
        if status != 'Idle':
            return

        if miner == 'org.freedesktop.Tracker1.Miner.Files':
            self.wait_files = False

        if miner == 'org.freedesktop.Tracker1.Miner.Extract':
            # If Files miner is not done yet, extractor will have more work to
            # do even if it's currently Idle waiting for the Files miner to be
            # done.
            if not self.wait_files:
                self.wait_extractor = False

        if not self.wait_files and not self.wait_extractor:
            print("TrackerIndexer: quit main loop")
            self.loop.quit()

    def start(self):
        print("TrackerIndexer: start")
        self.manager = TrackerControl.MinerManager.new_full(True)
        self.conn = Tracker.SparqlConnection.get(None)
        self.statuses = {}

        for miner in self.manager.get_available():
            status = self.manager.get_status(miner)[1]
            print("TrackerIndexer: Miner '%s' initial status is '%s'" %
                  (miner, status))
            self.statuses[miner] = status
        self.manager.connect('miner-progress', self.miner_progress_cb)

        # Wait for the initial indexing
        self.wait(True)

    # wait_extractor is used to tell if we expect the extractor to have work
    # to do and thus we should wait for it. For example when deleting files
    # we don't expect extractor to do anything.
    def wait(self, wait_extractor):
        self.wait_extractor = wait_extractor
        self.wait_files = True
        self.loop.run()

    def assert_indexed(self, path, extra=None):
        # Select entries for the given URL. Also check that is has the
        # tracker:extractor-data-source flag added by tracker-extract when
        # metadata has been extracted.
        query = ('select ?urn where { '
                 '  ?urn nie:url "file://%s" ; '
                 '  tracker:available true ; '
                 '  nie:dataSource tracker:extractor-data-source . ') % (path)
        if extra is not None:
            query += extra
        query += ' }'

        # Must have one and only one result
        cursor = self.conn.query(query, None)
        self.assertTrue(cursor.next(None))
        self.assertFalse(cursor.next(None))

    def assert_not_indexed(self, path):
        query = ('select ?urn where { ?urn nie:url "file://%s" }') % (path)
        cursor = self.conn.query(query, None)
        self.assertFalse(cursor.next(None))

    def assert_all_indexed(self, root):
        playable_query = '?urn bosch:playable true . '
        album_query = ('?urn nmm:musicAlbum ?album . '
                       '?album nmm:albumTitle "GNOME Audio" . ')
        performer_query = ('?urn nmm:performer ?performer . '
                           '?performer nmm:artistName "Conrad Parker" . ')
        title_query = '?urn nie:title "GNOME Generic Sound" . '
        audio_query = album_query + performer_query + title_query

        self.assert_indexed(root + '/Music/generic.mp3', audio_query)
        self.assert_indexed(root + '/Music/generic.flac',
                            audio_query + playable_query)
        self.assert_indexed(root + '/Music/generic-no-artwork.mp3',
                            audio_query)
        self.assert_indexed(root + '/Music/generic.oga', audio_query)
        self.assert_indexed(root + '/Music/generic.wav', playable_query)
        self.assert_indexed(root + '/Documents/lorem_presentation.odp')
        self.assert_indexed(root + '/Documents/lorem_spreadsheet.ods')
        self.assert_indexed(root + '/Documents/lorem_text.txt')
        self.assert_indexed(root + '/Documents/more_lorem_ipsum.odt')
        self.assert_indexed(root + '/Pictures/' + LONG_JPEG_NAME)
        self.assert_indexed(root + '/Pictures/collabora-logo-big.png')
        self.assert_indexed(root + '/Music/Generic_Sounds.pls',
                            '?urn nfo:entryCounter 3')
        self.assert_indexed(root + '/Music/Ghosts.pls',
                            '?urn nfo:entryCounter 38')
        self.assert_indexed(root + '/Music/Ghosts.m3u',
                            '?urn nfo:entryCounter 38')
        self.assert_indexed(root + '/Videos/big_buck_bunny_smaller.ogv',
                            playable_query)