#!/usr/bin/env python
###############################################################################
# libbrlapi - A library providing access to braille terminals for applications.
#
# Copyright (C) 2005-2023 by
#   Alexis Robert <alexissoft@free.fr>
#   Samuel Thibault <Samuel.Thibault@ens-lyon.org>
#
# libbrlapi comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU Lesser General Public License, as published by the Free Software
# Foundation; either version 2.1 of the License, or (at your option) any
# later version. Please see the file LICENSE-LGPL for details.
#
# Web Page: http://brltty.app/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################

import sys
import os

def putProgramMessage(message):
  sys.stderr.write("%s: %s%s" % (programName, message, os.linesep))

def syntaxError(message):
  putProgramMessage(message)
  sys.exit(2)

def nextProgramArgument():
  return sys.argv.pop(0)

def verifyNoMoreProgramArguments():
  if (len(sys.argv) > 0):
    syntaxError("too many parameters")

programPath = nextProgramArgument()
programName = os.path.basename(programPath)

try:
  actionName = nextProgramArgument()
except IndexError:
  syntaxError("action not specified")

try:
  import sysconfig
# putProgramMessage("sysconfig")
  if hasattr(sysconfig, 'get_default_scheme'):
    scheme = sysconfig.get_default_scheme()
  else:
    scheme = sysconfig._get_default_scheme()

  if scheme == 'posix_local':
    # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/
    scheme = 'posix_prefix'

  def getIncludeDirectory():
    return sysconfig.get_path("include", scheme)

  def getLibraryDirectory():
    return sysconfig.get_path("stdlib", scheme)

  def getPackageDirectory():
    return sysconfig.get_path("platlib", scheme)

  def getConfigurationVariable(name):
    return sysconfig.get_config_var(name)

except ModuleNotFoundError:
  from distutils import sysconfig
# putProgramMessage("distutils")

  def getIncludeDirectory():
    return sysconfig.get_python_inc()

  def getLibraryDirectory():
    return sysconfig.get_python_lib(0, 1)

  def getPackageDirectory():
    return sysconfig.get_python_lib(True, False)

  def getConfigurationVariable(name):
    return sysconfig.get_config_var(name)

class ActionHanlers:
  def version():
    verifyNoMoreProgramArguments()
    print(sys.version_info[0])

  def incdir():
    verifyNoMoreProgramArguments()
    print(getIncludeDirectory())

  def libdir():
    verifyNoMoreProgramArguments()
    print(getLibraryDirectory())

  def pkgdir():
    verifyNoMoreProgramArguments()
    print(getPackageDirectory())

  def libopts():
    verifyNoMoreProgramArguments()
    print(getConfigurationVariable("LIBS"))

  def linkopts():
    verifyNoMoreProgramArguments()
    print(getConfigurationVariable("LINKFORSHARED"))

actionHandlers = globals()["ActionHanlers"]

try:
  actionHandler = getattr(actionHandlers, actionName)
except AttributeError:
  syntaxError("unknown action: %s" % actionName)

actionHandler()
sys.exit(0)
