# Copyright (C) 2011 Igalia S.L.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

import errno
import logging
import os
import os.path
import subprocess
import sys

PY2 = sys.version_info[0] == 2

class GTKDoc(object):

    """Class that controls a gtkdoc run.

    Each instance of this class represents one gtkdoc configuration
    and set of documentation. The gtkdoc package is a series of tools
    run consecutively which converts inline C/C++ documentation into
    docbook files and then into HTML. This class is suitable for
    generating documentation or simply verifying correctness.

    Keyword arguments:
    output_dir         -- The path where gtkdoc output should be placed. Generation
                          may overwrite file in this directory. Required.
    module_name        -- The name of the documentation module. For libraries this
                          is typically the library name. Required if not library path
                          is given.
    source_dirs        -- A list of paths to directories of source code to be scanned.
                          Required if headers is not specified.
    ignored_files      -- A list of filenames to ignore in the source directory. It is
                          only necessary to provide the basenames of these files.
                          Typically it is important to provide an updated list of
                          ignored files to prevent warnings about undocumented symbols.
    headers            -- A list of paths to headers to be scanned. Required if source_dirs
                          is not specified.
    namespace          -- The library namespace.
    decorator          -- If a decorator is used to unhide certain symbols in header
                          files this parameter is required for successful scanning.
                          (default '')
    deprecation_guard  -- gtkdoc tries to ensure that symbols marked as deprecated
                          are encased in this C preprocessor define. This is required
                          to avoid gtkdoc warnings. (default '')
    cflags             -- This parameter specifies any preprocessor flags necessary for
                          building the scanner binary during gtkdoc-scanobj. Typically
                          this includes all absolute include paths necessary to resolve
                          all header dependencies. (default '')
    ldflags            -- This parameter specifies any linker flags necessary for
                          building the scanner binary during gtkdoc-scanobj. Typically
                          this includes "-lyourlibraryname". (default '')
    library_path       -- This parameter specifies the path to the directory where you
                          library resides used for building the scanner binary during
                          gtkdoc-scanobj. (default '')

    doc_dir            -- The path to other documentation files necessary to build
                          the documentation. This files in this directory as well as
                          the files in the 'html' subdirectory will be copied
                          recursively into the output directory. (default '')
    main_sgml_file     -- The path or name (if a doc_dir is given) of the SGML file
                          that is the considered the main page of your documentation.
                          (default: <module_name>-docs.sgml)
    version            -- The version number of the module. If this is provided,
                          a version.xml file containing the version will be created
                          in the output directory during documentation generation.

    interactive        -- Whether or not errors or warnings should prompt the user
                          to continue or not. When this value is false, generation
                          will continue despite warnings. (default False)

    virtual_root       -- A temporary installation directory which is used as the root
                          where the actual installation prefix lives; this is mostly
                          useful for packagers, and should be set to what is given to
                          make install as DESTDIR.
    """

    def __init__(self, args):

        # Parameters specific to scanning.
        self.module_name = ''
        self.source_dirs = []
        self.headers = []
        self.ignored_files = []
        self.namespace = ''
        self.decorator = ''
        self.deprecation_guard = ''

        # Parameters specific to gtkdoc-scanobj.
        self.cflags = ''
        self.ldflags = ''
        self.library_path = ''

        # Parameters specific to generation.
        self.output_dir = ''
        self.doc_dir = ''
        self.main_sgml_file = ''

        # Parameters specific to gtkdoc-fixxref.
        self.cross_reference_deps = []

        self.interactive = False

        self.logger = logging.getLogger('gtkdoc')

        for key, value in iter(args.items()):
            setattr(self, key, value)

        if not getattr(self, 'output_dir'):
            raise Exception('output_dir not specified.')
        if not getattr(self, 'module_name'):
            raise Exception('module_name not specified.')
        if not getattr(self, 'source_dirs') and not getattr(self, 'headers'):
            raise Exception('Neither source_dirs nor headers specified.' % key)

        # Make all paths absolute in case we were passed relative paths, since
        # we change the current working directory when executing subcommands.
        self.output_dir = os.path.abspath(self.output_dir)
        self.source_dirs = [os.path.abspath(x) for x in self.source_dirs]
        self.headers = [os.path.abspath(x) for x in self.headers]
        if self.library_path:
            self.library_path = os.path.abspath(self.library_path)

        if not self.main_sgml_file:
            self.main_sgml_file = self.module_name + "-docs.sgml"

    def generate(self, html=True):
        self.saw_warnings = False

        self._copy_doc_files_to_output_dir(html)
        self._write_version_xml()
        self._run_gtkdoc_scan()
        self._run_gtkdoc_scangobj()
        self._run_gtkdoc_mkdb()

        if not html:
            return

        self._run_gtkdoc_mkhtml()
        self._run_gtkdoc_fixxref()

    def _delete_file_if_exists(self, path):
        if not os.access(path, os.F_OK | os.R_OK):
            return
        self.logger.debug('deleting %s', path)
        os.unlink(path)

    def _create_directory_if_nonexistent(self, path):
        try:
            os.makedirs(path)
        except OSError as error:
            if error.errno != errno.EEXIST:
                raise

    def _raise_exception_if_file_inaccessible(self, path):
        if not os.path.exists(path) or not os.access(path, os.R_OK):
            raise Exception("Could not access file at: %s" % path)

    def _output_has_warnings(self, outputs):
        for output in outputs:
            if output and output.find('warning'):
                return True
        return False

    def _ask_yes_or_no_question(self, question):
        if not self.interactive:
            return True

        question += ' [y/N] '
        answer = None
        while answer != 'y' and answer != 'n' and answer != '':
            answer = raw_input(question).lower()
        return answer == 'y'

    def _run_command(self, args, env=None, cwd=None, print_output=True, ignore_warnings=False):
        if print_output:
            self.logger.debug("Running %s", args[0])
        self.logger.debug("Full command args: %s", str(args))

        process = subprocess.Popen(args, env=env, cwd=cwd,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout, stderr = [b.decode("utf-8") for b in process.communicate()]

        if print_output:
            if stdout:
                if PY2:
                    try:
                        sys.stdout.write(stdout.encode("utf-8"))
                    except UnicodeDecodeError:
                        sys.stdout.write(stdout)
                else:
                    sys.stdout.write(stdout)
            if stderr:
                if PY2:
                    try:
                        sys.stderr.write(stderr.encode("utf-8"))
                    except UnicodeDecodeError:
                        sys.stderr.write(stderr)
                else:
                    sys.stderr.write(stderr)

        if process.returncode != 0:
            raise Exception('%s produced a non-zero return code %i'
                             % (args[0], process.returncode))

        if not ignore_warnings and ('warning' in stderr or 'warning' in stdout):
            self.saw_warnings = True
            if not self._ask_yes_or_no_question('%s produced warnings, '
                                                'try to continue?' % args[0]):
                raise Exception('%s step failed' % args[0])

        return stdout.strip()

    def _copy_doc_files_to_output_dir(self, html=True):
        if not self.doc_dir:
            self.logger.info('Not copying any files from doc directory,'
                             ' because no doc directory given.')
            return

        def copy_file_replacing_existing(src, dest):
            if os.path.isdir(src):
                self.logger.debug('skipped directory %s',  src)
                return
            if not os.access(src, os.F_OK | os.R_OK):
                self.logger.debug('skipped unreadable %s', src)
                return

            self._delete_file_if_exists(dest)

            self.logger.debug('created %s', dest)
            try:
                os.link(src, dest)
            except OSError:
                os.symlink(src, dest)

        def copy_all_files_in_directory(src, dest):
            for path in os.listdir(src):
                copy_file_replacing_existing(os.path.join(src, path),
                                             os.path.join(dest, path))

        self.logger.debug('Copying template files to output directory...')
        self._create_directory_if_nonexistent(self.output_dir)
        copy_all_files_in_directory(self.doc_dir, self.output_dir)

        if not html:
            return

        self.logger.debug('Copying HTML files to output directory...')
        html_src_dir = os.path.join(self.doc_dir, 'html')
        html_dest_dir = os.path.join(self.output_dir, 'html')
        self._create_directory_if_nonexistent(html_dest_dir)

        if os.path.exists(html_src_dir):
            copy_all_files_in_directory(html_src_dir, html_dest_dir)

    def _write_version_xml(self):
        if not self.version:
            self.logger.info('No version specified, so not writing version.xml')
            return

        version_xml_path = os.path.join(self.output_dir, 'version.xml')
        src_version_xml_path = os.path.join(self.doc_dir, 'version.xml')

        # Don't overwrite version.xml if it was in the doc directory.
        if os.path.exists(version_xml_path) and \
           os.path.exists(src_version_xml_path):
            return

        output_file = open(version_xml_path, 'w')
        output_file.write(self.version)
        output_file.close()

    def _ignored_files_basenames(self):
        return ' '.join([os.path.basename(x) for x in self.ignored_files])

    def _run_gtkdoc_scan(self):
        args = ['gtkdoc-scan',
                '--module=%s' % self.module_name,
                '--rebuild-types']

        if not self.headers:
            # Each source directory should be have its own "--source-dir=" prefix.
            args.extend(['--source-dir=%s' % path for path in self.source_dirs])

        if self.decorator:
            args.append('--ignore-decorators=%s' % self.decorator)
        if self.deprecation_guard:
            args.append('--deprecated-guards=%s' % self.deprecation_guard)
        if self.output_dir:
            args.append('--output-dir=%s' % self.output_dir)

        # We only need to pass the list of ignored files if the we are not using an explicit list of headers.
        if not self.headers:
            # gtkdoc-scan wants the basenames of ignored headers, so strip the
            # dirname. Different from "--source-dir", the headers should be
            # specified as one long string.
            ignored_files_basenames = self._ignored_files_basenames()
            if ignored_files_basenames:
                args.append('--ignore-headers=%s' % ignored_files_basenames)

        if self.headers:
            args.extend(self.headers)

        self._run_command(args)

    def _run_gtkdoc_scangobj(self):
        env = os.environ
        ldflags = self.ldflags
        if self.library_path:
            additional_ldflags = ''
            for arg in env.get('LDFLAGS', '').split(' '):
                if arg.startswith('-L'):
                    additional_ldflags = '%s %s' % (additional_ldflags, arg)
            ldflags = ' "-L%s" %s ' % (self.library_path, additional_ldflags) + ldflags
            current_ld_library_path = env.get('LD_LIBRARY_PATH')
            if current_ld_library_path:
                env['LD_LIBRARY_PATH'] = '%s:%s' % (self.library_path, current_ld_library_path)
            else:
                env['LD_LIBRARY_PATH'] = self.library_path

        if ldflags:
            env['LDFLAGS'] = '%s %s' % (ldflags, env.get('LDFLAGS', ''))
        if self.cflags:
            env['CFLAGS'] = '%s %s' % (self.cflags, env.get('CFLAGS', ''))

        if 'CFLAGS' in env:
            self.logger.debug('CFLAGS=%s', env['CFLAGS'])
        if 'LDFLAGS' in env:
            self.logger.debug('LDFLAGS %s', env['LDFLAGS'])
        if 'RUN' in env:
            self.logger.debug('RUN=%s', env['RUN'])
        self._run_command(['gtkdoc-scangobj', '--module=%s' % self.module_name],
                          env=env, cwd=self.output_dir)

    def _run_gtkdoc_mkdb(self):
        sgml_file = os.path.join(self.output_dir, self.main_sgml_file)
        self._raise_exception_if_file_inaccessible(sgml_file)

        args = ['gtkdoc-mkdb',
                '--module=%s' % self.module_name,
                '--main-sgml-file=%s' % sgml_file,
                '--source-suffixes=h,c,cpp,cc',
                '--output-format=xml',
                '--sgml-mode']

        if self.namespace:
            args.append('--name-space=%s' % self.namespace)

        ignored_files_basenames = self._ignored_files_basenames()
        if ignored_files_basenames:
            args.append('--ignore-files=%s' % ignored_files_basenames)

        # Each directory should be have its own "--source-dir=" prefix.
        args.extend(['--source-dir=%s' % path for path in self.source_dirs])
        self._run_command(args, cwd=self.output_dir)

    def _run_gtkdoc_mkhtml(self):
        html_dest_dir = os.path.join(self.output_dir, 'html')
        if not os.path.isdir(html_dest_dir):
            raise Exception("%s is not a directory, could not generate HTML"
                            % html_dest_dir)
        elif not os.access(html_dest_dir, os.X_OK | os.R_OK | os.W_OK):
            raise Exception("Could not access %s to generate HTML"
                            % html_dest_dir)

        # gtkdoc-mkhtml expects the SGML path to be absolute.
        sgml_file = os.path.join(os.path.abspath(self.output_dir),
                                 self.main_sgml_file)
        self._raise_exception_if_file_inaccessible(sgml_file)

        self._run_command(['gtkdoc-mkhtml', self.module_name, sgml_file],
                          cwd=html_dest_dir)

    def _run_gtkdoc_fixxref(self):
        args = ['gtkdoc-fixxref',
                '--module=%s' % self.module_name,
                '--module-dir=html',
                '--html-dir=html']
        args.extend(['--extra-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
        self._run_command(args, cwd=self.output_dir, ignore_warnings=True)

    def rebase_installed_docs(self):
        if not os.path.isdir(self.output_dir):
            raise Exception("Tried to rebase documentation before generating it.")
        html_dir = os.path.join(self.virtual_root + self.prefix, 'share', 'gtk-doc', 'html', self.module_name)
        if not os.path.isdir(html_dir):
            return
        args = ['gtkdoc-rebase',
                '--relative',
                '--html-dir=%s' % html_dir]
        args.extend(['--other-dir=%s' % extra_dir for extra_dir in self.cross_reference_deps])
        if self.virtual_root:
            args.extend(['--dest-dir=%s' % self.virtual_root])
        self._run_command(args, cwd=self.output_dir)

    def api_missing_documentation(self):
        unused_doc_file = os.path.join(self.output_dir, self.module_name + "-unused.txt")
        if not os.path.exists(unused_doc_file) or not os.access(unused_doc_file, os.R_OK):
            return []
        return open(unused_doc_file).read().splitlines()

class PkgConfigGTKDoc(GTKDoc):

    """Class reads a library's pkgconfig file to guess gtkdoc parameters.

    Some gtkdoc parameters can be guessed by reading a library's pkgconfig
    file, including the cflags, ldflags and version parameters. If you
    provide these parameters as well, they will be appended to the ones
    guessed via the pkgconfig file.

    Keyword arguments:
      pkg_config_path -- Path to the pkgconfig file for the library. Required.
    """

    def __init__(self, pkg_config_path, args):
        super(PkgConfigGTKDoc, self).__init__(args)

        pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')

        if not os.path.exists(pkg_config_path):
            raise Exception('Could not find pkg-config file at: %s'
                            % pkg_config_path)

        self.cflags += " " + self._run_command([pkg_config,
                                                pkg_config_path,
                                                '--cflags'], print_output=False)
        self.ldflags += " " + self._run_command([pkg_config,
                                                pkg_config_path,
                                                '--libs'], print_output=False)
        self.version = self._run_command([pkg_config,
                                          pkg_config_path,
                                          '--modversion'], print_output=False)
        self.prefix = self._run_command([pkg_config,
                                         pkg_config_path,
                                         '--variable=prefix'], print_output=False)
