#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# autolatex/utils/utils.py
# Copyright (C) 2013  Stephane Galland <[email protected]>
#
# 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 of the License, 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 this program; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

#---------------------------------
# IMPORTS
#---------------------------------

# Import standard python libs
import os
import sys
import subprocess
import ConfigParser
import StringIO
import gettext

#---------------------------------
# UTILITY FUNCTION
#---------------------------------

# Search an executable in the PATH
def which(cmd):
 # can't search the path if a directory is specified
 assert not os.path.dirname(cmd)
 extensions = os.environ.get("PATHEXT", "").split(os.pathsep)
 for directory in os.environ.get("PATH", "").split(os.pathsep):
   base = os.path.join(directory, cmd)
   options = [base] + [(base + ext) for ext in extensions]
   for filename in options:
     if os.path.exists(filename):
       return filename
 return None

# Search a module in the sys.path or in search_part
def resolve_module_path(path, search_path=[]):
       if not os.path.isabs(path):
               for p in search_path:
                       full_name = os.path.join(p, path)
                       if os.path.exists(full_name):
                               return full_name
               for p in sys.path:
                       full_name = os.path.join(p, path)
                       if os.path.exists(full_name):
                               return full_name
       return path

#---------------------------------
# CONSTANTS
#---------------------------------

# Level of verbosity of AutoLaTeX
DEFAULT_LOG_LEVEL = '--quiet'

# String that is representing an empty string for the AutoLaTeX backend.
CONFIG_EMPTY_VALUE = '<<<<empty>>>>'

# Paths
AUTOLATEX_PLUGIN_PATH = None
AUTOLATEX_DEV_PATH = None
AUTOLATEX_INSTALL_PATH = None
AUTOLATEX_PO_PATH = None # Default locale path
AUTOLATEX_PM_PATH = None
TOOLBAR_ICON_PATH = None
NOTEBOOK_ICON_PATH = None
TABLE_ICON_PATH = None

# Binary files
AUTOLATEX_BINARY = None
DEFAULT_AUTOLATEX_BINARY = None
AUTOLATEX_BACKEND_BINARY = None
DEFAULT_AUTOLATEX_BACKEND_BINARY = None

def init_plugin_configuration(plugin_file, po_name, search_path=[]):
       global AUTOLATEX_PLUGIN_PATH
       global AUTOLATEX_DEV_PATH
       global AUTOLATEX_INSTALL_PATH
       global AUTOLATEX_PO_PATH
       global AUTOLATEX_PM_PATH
       global AUTOLATEX_BINARY
       global AUTOLATEX_BACKEND_BINARY
       global DEFAULT_AUTOLATEX_BINARY
       global DEFAULT_AUTOLATEX_BACKEND_BINARY
       global TOOLBAR_ICON_PATH
       global NOTEBOOK_ICON_PATH
       global TABLE_ICON_PATH

       bin_autolatex = which('autolatex')

       # Build the plugin's filename
       plugin_file = resolve_module_path(plugin_file, search_path)

       # Path of the plugin
       AUTOLATEX_PLUGIN_PATH = os.path.dirname(plugin_file)

       # Path to the development directory
       pdev_path = os.path.realpath(os.path.join(AUTOLATEX_PLUGIN_PATH,
                       os.path.basename(os.path.splitext(plugin_file)[0])+'.py'))
       dev_path = os.path.dirname(pdev_path)
       while dev_path and pdev_path and pdev_path!=dev_path and not os.path.exists(
                               os.path.join(dev_path, 'autolatex.pl')):
               pdev_path = dev_path
               dev_path = os.path.dirname(dev_path)
       if dev_path and os.path.isfile(os.path.join(dev_path, 'autolatex.pl')):
               AUTOLATEX_DEV_PATH = dev_path
       else:
               dev_path = os.path.realpath(bin_autolatex)
               if dev_path:
                       AUTOLATEX_DEV_PATH = os.path.dirname(dev_path)
               else:
                       AUTOLATEX_DEV_PATH = None


       # Path to the install directory
       if AUTOLATEX_DEV_PATH:
               AUTOLATEX_INSTALL_PATH = AUTOLATEX_DEV_PATH
       else:
               path = os.path.realpath(bin_autolatex)
               AUTOLATEX_INSTALL_PATH = os.path.dirname(path)

       # Path to PO files
       AUTOLATEX_PO_PATH = None
       if AUTOLATEX_DEV_PATH:
               path = os.path.join(AUTOLATEX_DEV_PATH, 'po')
               if os.path.exists(os.path.join(path, 'fr', 'LC_MESSAGES', po_name+'.mo')):
                       AUTOLATEX_PO_PATH = path

       # Path to PM files
       AUTOLATEX_PM_PATH = os.path.join(AUTOLATEX_INSTALL_PATH, 'pm')

       # Binary file
       AUTOLATEX_BINARY = bin_autolatex
       if AUTOLATEX_DEV_PATH:
               path = os.path.join(dev_path, 'autolatex.pl')
               if os.path.exists(path):
                       AUTOLATEX_BINARY = path
       DEFAULT_AUTOLATEX_BINARY = AUTOLATEX_BINARY

       AUTOLATEX_BACKEND_BINARY = which('autolatex-backend')
       if AUTOLATEX_DEV_PATH:
               path = os.path.join(dev_path, 'autolatex-backend.pl')
               if os.path.exists(path):
                       AUTOLATEX_BACKEND_BINARY = path
       DEFAULT_AUTOLATEX_BACKEND_BINARY = AUTOLATEX_BACKEND_BINARY

       # Icons paths
       TOOLBAR_ICON_PATH = os.path.join(AUTOLATEX_PLUGIN_PATH, 'icons', '24')
       NOTEBOOK_ICON_PATH = os.path.join(AUTOLATEX_PLUGIN_PATH, 'icons', '16')
       TABLE_ICON_PATH = os.path.join(AUTOLATEX_PLUGIN_PATH, 'icons', '16')

       # Init internationalization tools
       gettext.bindtextdomain(po_name, AUTOLATEX_PO_PATH)
       gettext.textdomain(po_name)

def make_toolbar_icon_path(name):
       assert TOOLBAR_ICON_PATH
       return os.path.join(TOOLBAR_ICON_PATH, name)

def make_notebook_icon_path(name):
       assert NOTEBOOK_ICON_PATH
       return os.path.join(NOTEBOOK_ICON_PATH, name)

def make_table_icon_path(name):
       assert TABLE_ICON_PATH
       return os.path.join(TABLE_ICON_PATH, name)



def backend_get_translators(directory):
       os.chdir(directory)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'get', 'translators'], stdout=subprocess.PIPE )
       data = process.communicate()[0]
       string_in = StringIO.StringIO(data)
       config = ConfigParser.ConfigParser()
       config.readfp(string_in)
       string_in.close()
       return config

def backend_get_loads(directory):
       os.chdir(directory)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'get', 'loads', ], stdout=subprocess.PIPE )
       data = process.communicate()[0]
       string_in = StringIO.StringIO(data)
       config = ConfigParser.ConfigParser()
       config.readfp(string_in)
       string_in.close()
       return config

def backend_get_configuration(directory, level, section):
       os.chdir(directory)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'get', 'config', level, section], stdout=subprocess.PIPE )
       data = process.communicate()[0]
       string_in = StringIO.StringIO(data)
       config = ConfigParser.ConfigParser()
       config.readfp(string_in)
       string_in.close()
       return config

def backend_get_images(directory):
       os.chdir(directory)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'get', 'images'], stdout=subprocess.PIPE )
       data = process.communicate()[0]
       string_in = StringIO.StringIO(data)
       config = ConfigParser.ConfigParser()
       config.readfp(string_in)
       string_in.close()
       return config

def backend_set_loads(directory, load_config):
       os.chdir(directory)
       string_out = StringIO.StringIO()
       load_config.write(string_out)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'set', 'loads', ], stdin=subprocess.PIPE)
       process.communicate(input=string_out.getvalue())
       string_out.close()
       return process.returncode == 0

def backend_set_configuration(directory, level, settings):
       os.chdir(directory)
       string_out = StringIO.StringIO()
       settings.write(string_out)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'set', 'config', level, 'false' ], stdin=subprocess.PIPE)
       process.communicate(input=string_out.getvalue())
       string_out.close()
       return process.returncode == 0

def backend_set_images(directory, settings):
       os.chdir(directory)
       string_out = StringIO.StringIO()
       settings.write(string_out)
       process = subprocess.Popen( [AUTOLATEX_BACKEND_BINARY, 'set', 'images', 'false' ], stdin=subprocess.PIPE)
       process.communicate(input=string_out.getvalue())
       string_out.close()
       return process.returncode == 0


def first_of(*values):
       for value in values:
               if value is not None:
                       return value
       return None

def get_autolatex_user_config_directory():
       if os.name == 'posix':
               return os.path.join(os.path.expanduser("~"), ".autolatex")
       elif os.name == 'nt':
               return  os.path.join(os.path.expanduser("~"),"Local Settings","Application Data","autolatex")
       else:
               return os.path.join(os.path.expanduser("~"), "autolatex")

def get_autolatex_user_config_file():
       directory = get_autolatex_user_config_directory()
       if os.path.isdir(directory):
               return os.path.join(directory, 'autolatex.conf')
       if os.name == 'posix':
               return os.path.join(os.path.expanduser("~"), ".autolatex")
       elif os.name == 'nt':
               return  os.path.join(os.path.expanduser("~"),"Local Settings","Application Data","autolatex.conf")
       else:
               return os.path.join(os.path.expanduser("~"), "autolatex.conf")

def get_autolatex_document_config_file(directory):
       if os.name == 'posix':
               return os.path.join(directory, ".autolatex_project.cfg")
       else:
               return os.path.join(directory, "autolatex_project.cfg")

# Test if a given string is a standard extension for TeX document
def is_TeX_extension(ext):
       ext = ext.lower()
       if ext == '.tex' or ext =='.latex':
               return True
       else:
               return False

# Replies if the active document is a TeX document
def is_TeX_document(filename):
       if filename:
               ext = os.path.splitext(filename)[-1]
               return is_TeX_extension(ext)
       return False

# Try to find the directory where an AutoLaTeX configuration file is
# located. The search is traversing the parent directory from the current
# document.
def find_AutoLaTeX_directory(current_document):
       adir = None
       if os.path.isdir(current_document):
               directory = current_document
       else:
               directory = os.path.dirname(current_document)
       directory = os.path.abspath(directory)
       document_dir = directory
       cfgFile = get_autolatex_document_config_file(directory)
       previousFile = ''
       while previousFile != cfgFile and not os.path.exists(cfgFile):
           directory = os.path.dirname(directory)
           previousFile = cfgFile
           cfgFile = get_autolatex_document_config_file(directory)

       if previousFile != cfgFile:
           adir = os.path.dirname(cfgFile)
       else:
           ext = os.path.splitext(current_document)[-1]
           if is_TeX_extension(ext):
               adir = document_dir

       return adir