#coding:utf-8
#########################################################################
"""  minimalconfig.py -- Minimal configuration for IDE

Copyright (c) 1999-2018, Archaeopteryx Software, Inc.  All rights reserved.

Written by Stephan R.A. Deibel and John P. Ehresman

"""
#########################################################################

# This file needs to work with all supported versions of Python

# IMPORTANT:  This module should import as little as possible --
# it gets imported before we install our update manager so anything
# imported here cannot be updated!

# Implementation note: print statements can throw exceptions because
# of unicode conversion failures

import sys
import os

#----------------------------------------------------------------------
def NP_LoadModuleHere(modname):
  """Load the given module from same directory as this file
  without adding it to sys.modules"""
  
  sys.modules.pop(modname, None)
  
  sys.path.insert(0, os.path.dirname(__file__))
  exec('import %s' % modname)
  sys.modules.pop(modname, None)
  
  sys.path = sys.path[1:]
  return locals()[modname]

bootstrap_utils = NP_LoadModuleHere('bootstrap_utils')

# Make sure we get the right values if debugging Wing with itself
bootstrap_vinfo = NP_LoadModuleHere('bootstrap_vinfo')
kInstallVersion = bootstrap_vinfo.kInstallVersion
kProduct = bootstrap_vinfo.kProduct
kOSXBundleName = bootstrap_vinfo.kOSXBundleName
kOSXBundleIdentifier = bootstrap_vinfo.kOSXBundleIdentifier

kMajorVersion = kInstallVersion[0]

# Product codes
kProdPersonal = 0x00000001
kProdProfessional = 0x00000002
kProd101 = 0x00000008

if kProduct.lower().strip()[:3] == 'pro':
  kRunningProduct = kProdProfessional
elif kProduct.lower().strip()[:3] == 'per':
  kRunningProduct = kProdPersonal
else:
  kRunningProduct = kProd101

# Product names
kProductNames = {
  kProd101: '101',
  kProdPersonal: 'Personal',
  kProdProfessional: 'Pro',
}

for key, value in kProductNames.items():
    if value == kProduct:
        kProductCode = key
        break
kProductName = "Wing %s" % kProduct

# Define file system encoding; note that it can be None and defaults to default encoding
# if it is
kFileSystemEncoding = sys.getfilesystemencoding()
if kFileSystemEncoding is None:
    kFileSystemEncoding = sys.getdefaultencoding()

import _winghome
kWingHome = _winghome.kWingHome

def GetUserSettingsDir(major_version, platform=sys.platform, create=True):
    """Get the user settings dir for given version of Wing and platform.  This
    records the history of how the settings directory names have changed over
    time, so that we can pull old settings during upgrades.  When platform
    is None, unconditionally returns the Posix dot directory."""

    def get_posix_dir(major_version):
        if kProduct == '101':
            dirname = '.wing101-%d' % major_version
        elif kProduct == 'Personal' and major_version >= 3:
            dirname = '.wingpersonal%d' % major_version
        else:
            if major_version <= 6:
                dirname = '.wingide%d' % major_version
            else:
                dirname = '.wingpro%d' % major_version
        base_dir = os.path.join(os.path.expanduser('~'), dirname)
        return base_dir
        
    def get_win32_dir(major_version):
        import minimalwin32
        try:
            app_dir = minimalwin32.SHGetFolderPath(minimalwin32.CSIDL_APPDATA, True)
        except:
            app_dir = bootstrap_utils._NP_GetUnicodeEnvValue('APPDATA')
            
        if kProduct == '101':
            if major_version <= 6:
                subdir = 'Wing IDE 101 %d' % major_version
            else:
                subdir = 'Wing 101 %d' % major_version
        elif kProduct == 'Personal' and major_version >= 3:
            if major_version <= 6:
                subdir = 'Wing IDE Personal %d' % major_version
            else:
                subdir = 'Wing Personal %d' % major_version
        else:
            if major_version <= 6:
                subdir = 'Wing IDE %d' % major_version
            else:
                subdir = 'Wing Pro %d' % major_version

        base_dir = os.path.join(app_dir, subdir)
        return base_dir
        
    def get_cyg_path_for_win_path(p):
    
        if platform != 'cygwin' or not os.path.isdir('/cygdrive'):
            return p
    
        if len(p) < 3 or not p[0].isalpha() or p[1] != ':' or p[2] not in ('\\', '/'):
            return p
    
        return '/cygdrive/' + p[0].lower() + '/' + p[2:].replace('\\', '/')
        
    # Compute fallback directory to use if regular default cannot be created
    if kWingHome is not None and major_version == kMajorVersion:
      fallback_userdir = os.path.join(kWingHome, 'user-settings')
    else:
      fallback_userdir = None
      
    if platform is not None and major_version == kMajorVersion:

      # Determine if user passed in an alternative user settings directory
      if _winghome.kUserSettings is not None:
        return _winghome.kUserSettings

      settings = None
      try:
        argv = sys.argv
      except AttributeError:
        argv = []
        
      for arg in argv:
          if arg.startswith('--settings='):
              sys.argv.remove(arg)
              settings = arg[len('--settings='):]
              _winghome.kUserSettings = settings
              if not os.path.exists(settings):
                  if os.path.exists(os.path.dirname(settings)):
                      os.mkdir(settings)
                      break
                  else:
                      try:
                          print("Cannot create designated settings directory", settings)
                      except:
                          pass
                      settings = None
      if settings:
          return settings
        
      # Let WINGHOME/user-settings override the default location, if present
      if fallback_userdir is not None and os.path.exists(fallback_userdir):
        return fallback_userdir

    # Special case cygwin: use ~/wing<product> if it exists and contains 1+
    # files / subdirs, otherwise use cygwin path to win32 settings directory
    if platform == 'cygwin':
        base_dir = get_posix_dir()
        try:
            use_cygwin_home = (len(os.listdir(base_dir)) != 0)
        except OSError:
            use_cygwin_home = False
      
        if not use_cygwin_home:
            base_dir = get_cyg_path_for_win_path(get_win32_dir(major_version))

    elif platform == 'win32':
        base_dir = get_win32_dir(major_version)
                
    elif platform == 'darwin' and major_version >= 5:
        if kProduct == 'Pro' and major_version <= 6:
            base_dir = os.path.expanduser('~/Library/Application Support/%s/v%s'
                                                  % ("Wing IDE", major_version))
        else:
            base_dir = os.path.expanduser('~/Library/Application Support/%s/v%s'
                                                  % (kOSXBundleName, major_version))
        
    else:
        base_dir = get_posix_dir(major_version)

    if sys.version_info < (3, 0) and not isinstance(base_dir, unicode):
        base_dir = unicode(base_dir, kFileSystemEncoding, 'strict')
    
    # Work around bug in os.path.join on win32
    if base_dir.replace('\\', '/').startswith('//'):
        return os.path.normpath(base_dir)
    
    if sys.version_info < (3, 0):
        cwd = os.getcwdu()
    else:
        cwd = os.getcwd()
        
    userdir = os.path.normpath(os.path.join(cwd, base_dir))

    # Make sure it exists if for currently running version
    def try_create(dirname):
      if os.path.exists(dirname) or major_version != kMajorVersion:
        return True
      
      try:
        CACHE_DIR_UMASK = 0x1c0  # 0o700 in a form that works w/ all Python versions
        os.makedirs(dirname, CACHE_DIR_UMASK)
        return True
      except:
        return False
      
    # Try to create dir if missing; fail silently so debugger can run on hosts w/ r/o file system
    if create and not try_create(userdir):
      #print("FAILURE: Could not create user directory: %s\n" % repr(userdir))
      if fallback_userdir is not None:
        #print("Falling back to using %s\n" % repr(fallback_settings))
        userdir = fallback_userdir
        if not try_create(userdir):
          #print("ERROR: Also failed to create fallback user directory: %s\n" % userdir)
          pass

    return userdir

kUserSettings = GetUserSettingsDir(kMajorVersion)

def GetOldUserSettingsDir():
    """Get next most recent user settings dir, for Wing version before the current one"""
    
    for i in range(kMajorVersion-1, 1, -1):
        old_dir = GetUserSettingsDir(i)
        if os.path.exists(old_dir):
            return old_dir
        
    return None

def _GetDefaultCacheDir(major_version):

    # Determine if user passed in an alternative cache directory
    if _winghome.kCacheDir is not None:
      return _winghome.kCacheDir

    cache_dir = None
    try:
      argv = sys.argv
    except AttributeError:
      argv = []
      
    for arg in argv:
        if arg.startswith('--cache='):
            sys.argv.remove(arg)
            cache_dir = arg[len('--cache='):]
            _winghome.kCacheDir = cache_dir
            if not os.path.exists(cache_dir):
                if os.path.exists(os.path.dirname(cache_dir)):
                    os.mkdir(cache_dir)
                    break
                else:
                    try:
                        print("Cannot create designated cache directory", cache_dir)
                    except:
                        pass
                    cache_dir = None
    if cache_dir:
        return cache_dir

    if sys.platform == 'win32':
        import minimalwin32
        if major_version >= 2:
            try:
                app_dir = minimalwin32.SHGetFolderPath(minimalwin32.CSIDL_LOCAL_APPDATA, True)
            except:
                pass
            else:
                if kProduct == '101':
                    return os.path.join(app_dir, 'Wing 101 %d' % major_version)
                elif kProduct == 'Personal' and major_version >= 3:
                    return os.path.join(app_dir, 'Wing Personal %d' % major_version)
                else:
                    # XXX Change to Wing Pro %d in Wing 7+
                    return os.path.join(app_dir, 'Wing Pro %d' % major_version)
    elif sys.platform == 'darwin' and major_version >= 5:
        base_dir = os.path.expanduser('~/Library/Caches/%s/v%s'
                                      % (kOSXBundleIdentifier, major_version))
        if sys.version_info < (3, 0, 0):
            return unicode(base_dir, kFileSystemEncoding, 'strict')
        else:
            return base_dir
    else:
        if major_version >= 4:
            xdg_cache_dir = os.environ.get('XDG_CACHE_DIR')
            if xdg_cache_dir is None:
                xdg_cache_dir = os.path.join(os.path.expanduser('~'), '.cache')
            if kProduct == '101':
                base_dir = os.path.join(xdg_cache_dir, 'wing101-%d' % major_version)
            elif kProduct == 'Personal':
                base_dir = os.path.join(xdg_cache_dir, 'wingpersonal%d' % major_version)      
            else:
                base_dir = os.path.join(xdg_cache_dir, 'wingpro%d' % major_version)
            if sys.version_info < (3, 0, 0):
                return unicode(base_dir, kFileSystemEncoding, 'strict')
            else:
                return base_dir

    return GetUserSettingsDir(major_version)

kCacheDir = _GetDefaultCacheDir(kMajorVersion)

