# -*- coding: utf-8 -*-
# PEP8:NO, LINT:OK, PY3:NO


#############################################################################
## This file may be used under the terms of the GNU General Public
## License version 2.0 or 3.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of
## this file.  Please review the following information to ensure GNU
## General Public Licensing requirements will be met:
## http:#www.fsf.org/licensing/licenses/info/GPLv2.html and
## http:#www.gnu.org/copyleft/gpl.html.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#############################################################################


# metadata
" Sublime Text 3 Snippets "
__version__ = ' 0.1 '
__license__ = ' GPL '
__author__ = ' juancarlospaco '
__email__ = ' juancarlospaco@ubuntu.com '
__url__ = ''
__date__ = ' 12/12/2013 '
__prj__ = ' sublime_snippets '
__docformat__ = 'html'
__source__ = ''
__full_licence__ = ''


# imports
from os import path, walk
from sys import platform
from datetime import datetime
from getpass import getuser

from PyQt4.QtGui import QAction, QFileDialog, QMenu
from xmltodict import parse

from ninja_ide.core import plugin


# sublimetext.info/docs/en/extensibility/snippets.html#snippets-file-format
TEMPLATE = """<snippet>
    <!-- {} by {} Sublime Text 3 Snippets by Ninja-IDE -->
    <content><![CDATA[Type your snippet here]]></content>
    <!-- Optional: Tab trigger to activate the snippet -->
    <tabTrigger>ninja_ide_rocks</tabTrigger>
    <!-- Optional: Scope the tab trigger will be active in -->
    <scope>source.python</scope>
    <!-- Optional: Description to show in the menu -->
    <description>{}s Fancy Snippet</description>
</snippet>


<!-- HELP: Environment Variables you can use inside the snippet content tag

$SELECTION............ The text that was selected when the snippet was triggered
$TM_CURRENT_LINE...Content of line the cursor was when the snippet was triggered
$TM_CURRENT_WORD....Current word under the cursor when the snippet was triggered
$TM_FILENAME..............File name of the file being edited including extension
$TM_FILEPATH..................................File path to the file being edited
$TM_FULLNAME.......................................................Your username
$TM_LINE_INDEX..................Column the snippet is being inserted at, 0 based
$TM_SELECTED_TEXT........................................An alias for $SELECTION
$TM_SOFT_TABS............................................................... YES
$TM_TAB_SIZE...................................................................4
-->
""".format(datetime.now().isoformat().split('.')[0], getuser(), getuser())
# http://docs.sublimetext.info/en/latest/basic_concepts.html#the-data-directory
if 'linux' in platform:
    DEFAULT_PATH = path.join(path.expanduser('~'), '.config', 'sublime-text-3',
                             'Packages', 'User')
elif 'darwin' in platform:
    DEFAULT_PATH = path.join(path.expanduser('~'), 'Library',
                   'Application Support', 'Sublime Text 3', 'Packages', 'User')
else:
    # http://technet.microsoft.com/en-us/library/cc962614.aspx   > Win2000 ?
    DEFAULT_PATH = path.join('%APPDATA%', 'Sublime Text 3', 'Packages', 'User')
if not path.isdir(DEFAULT_PATH):  # directory does not exist fallback to home
    DEFAULT_PATH = path.expanduser('~')


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


class Main(plugin.Plugin):
    " Main Class "
    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.menu, self.qactions = QMenu(__doc__), []
        self.menu.aboutToShow.connect(self.build_submenu)
        self.new_snipe = QAction('New Snippet', self, triggered=lambda:
            self.locator.get_service("editor").add_editor(content=TEMPLATE, ))
        self.locator.get_service("menuApp").add_menu(self.menu)

    def build_submenu(self):
        '''Build sub menu on the fly based on the available qactions'''
        self.menu.clear()
        if len(self.qactions):
            self.menu.addAction(self.new_snipe)
            self.menu.addSeparator()
            self.menu.addActions(sorted(list(set(self.qactions))))
        else:
            self.menu.addActions([self.new_snipe, QAction('Load Snippets', self,
            triggered=lambda: self.menu.addActions(sorted(self.run())))])

    def run(self):
        """Get directory,walk it,make list of snippets,convet them to Qaction"""
        dir_walk = QFileDialog.getExistingDirectory(None, __doc__, DEFAULT_PATH)
        list_of_files = self.walkdir_to_filelist(dir_walk)
        return self.snippets_to_qactions(list_of_files)

    def walkdir_to_filelist(self, where):
        """Perform full walk of where, gather full path of all files"""
        return [path.join(root, f) for root, d, files in walk(str(where))
                for f in files if f.lower().endswith('.sublime-snippet')]

    def snippets_to_qactions(self, list_of_files):
        """ takes a list of full paths and adds them as qactions on the menu """
        for snippet_file in list_of_files:
            with open(snippet_file, 'r') as snippet:
                sni = parse(str(snippet.read()).strip())
                try:
                    self.qactions.append(QAction(str(
                    '[{}] '.format(sni['snippet']['scope'].split('.')[1][:9]) +
                    sni['snippet']['description'][:99]), self, triggered=lambda:
                    self.locator.get_service("editor").insert_text(
                    self.snippet_replacer(str(sni['snippet']['content'])))))
                except:
                    pass
                snippet.flush()
        return self.qactions

    def snippet_replacer(self, snippetext):
        """ replaces the env vars by user input values or guessed values """
        # sublimetext.info/docs/en/extensibility/snippets.html#environment-variables
        #OPTIMIZE: how can we do this better?
        return snippetext.replace(
                '$SELECTION',
                self.locator.get_service("editor").get_actual_tab().textCursor().selectedText(),
            ).replace(
                '$TM_SELECTED_TEXT',
                self.locator.get_service("editor").get_actual_tab().textCursor().selectedText(),
            ).replace(
                '$TM_CURRENT_LINE',
                self.locator.get_service("editor").get_actual_tab().textCursor().block().text()
            ).replace(
                '$TM_FILENAME',
                path.basename(self.locator.get_service("editor").get_opened_documents()[self.locator.get_service("editor").get_tab_manager().currentIndex()])
            ).replace(
                '$TM_FILEPATH',
                path.dirname(self.locator.get_service("editor").get_opened_documents()[self.locator.get_service("editor").get_tab_manager().currentIndex()])
            ).replace(
                '$TM_LINE_INDEX',
                str(len(self.locator.get_service("editor").get_actual_tab().textCursor().block().text()))
            ).replace('$TM_SOFT_TABS', 'YES').replace('$TM_FULLNAME', getuser()
            ).replace('$TM_TAB_SIZE', '4')
            # ).replace(  #FIXME: how to get word under text cursor on ninja ?
                # '$TM_CURRENT_WORD',
                # self.locator.get_service("editor").get_actual_tab().textCursor().text()[self.locator.get_service("editor").get_actual_tab().getCursorPosition()[1]]


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


if __name__ == "__main__":
    print(__doc__)
