# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
#    * Redistributions of source code must retain the above copyright notice,
#      this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright notice,
#      this list of conditions and the following disclaimer in the documentation
#      and/or other materials provided with the distribution.
#    * Neither the name of Virtual Cable S.L. nor the names of its contributors
#      may be used to endorse or promote products derived from this software
#      without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
from __future__ import unicode_literals

import os
import locale
import subprocess
import ctypes
import base64
from ctypes.wintypes import DWORD, LPCWSTR
import win32com.client  # @UnresolvedImport, pylint: disable=import-error
import win32net  # @UnresolvedImport, pylint: disable=import-error
import win32security  # @UnresolvedImport, pylint: disable=import-error
import win32api  # @UnresolvedImport, pylint: disable=import-error
import win32con  # @UnresolvedImport, pylint: disable=import-error

from opengnsys import utils
from opengnsys.log import logger


def getNetworkInfo():
    '''
    Obtains a list of network interfaces
    @return: A "generator" of elements, that are dict-as-object, with this elements:
      name: Name of the interface
      mac: mac of the interface
      ip: ip of the interface
    '''
    obj = win32com.client.Dispatch("WbemScripting.SWbemLocator")
    wmobj = obj.ConnectServer("localhost", "root\\cimv2")
    adapters = wmobj.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IpEnabled=True")
    try:
        for obj in adapters:
            if obj.DefaultIPGateway is None:   # Skip adapters without default router
                continue
            for ip in obj.IPAddress:
                if ':' in ip:  # Is IPV6, skip this
                    continue
                if ip is None or ip == '' or ip.startswith('169.254') or ip.startswith('0.'):  # If single link ip, or no ip
                    continue
                logger.debug('Net config found: {}=({}, {})'.format(obj.Caption, obj.MACAddress, ip))
                yield utils.Bunch(name=obj.Caption, mac=obj.MACAddress, ip=ip)
    except Exception:
        return


def getWindowsVersion():
    '''
    Returns Windows version.
    '''
    import winreg
    reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion')
    try:
        data = '{} {}'.format(winreg.QueryValueEx(reg, 'ProductName')[0], winreg.QueryValueEx(reg, 'ReleaseId')[0])
    except Exception:
        data = '{} {}'.format(winreg.QueryValueEx(reg, 'ProductName')[0], winreg.QueryValueEx(reg, 'CurrentBuildNumber')[0])
    reg.Close()
    return data


EWX_LOGOFF = 0x00000000
EWX_SHUTDOWN = 0x00000001
EWX_REBOOT = 0x00000002
#EWX_FORCE = 0x00000004
#EWX_POWEROFF = 0x00000008
EWX_FORCEIFHUNG = 0x00000010


def reboot(flags=EWX_FORCEIFHUNG | EWX_REBOOT):
    hproc = win32api.GetCurrentProcess()
    htok = win32security.OpenProcessToken(hproc, win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY)
    privs = ((win32security.LookupPrivilegeValue(None, win32security.SE_SHUTDOWN_NAME), win32security.SE_PRIVILEGE_ENABLED),)
    win32security.AdjustTokenPrivileges(htok, 0, privs)
    win32api.ExitWindowsEx(flags, 0)

def poweroff(flags=0):
    '''
    Simple poweroff command.
    '''
    reboot(flags=EWX_FORCEIFHUNG | EWX_SHUTDOWN)

def logoff():
    win32api.ExitWindowsEx(EWX_LOGOFF)


def getCurrentUser():
    '''
    Returns current logged in username
    '''
    return os.environ['USERNAME']


def getSessionLanguage():
    '''
    Returns the user's session language
    '''
    return locale.getdefaultlocale()[0]


def get_session_type():
    """
    returns the user's session type (Local session, RDP,...)
    :return: string
    """
    return os.environ.get('SESSIONNAME').lower()


def showPopup(title, message):
    '''
    Displays a message box on user's session (during 1 min).
    '''
    return subprocess.call('mshta "javascript:var sh=new ActiveXObject(\'WScript.Shell\'); sh.Popup( \'{}\', 60, \'{}\', 64); close()"'.format(message.encode('unicode_escape'), title.encode('unicode_escape')), shell=True)


def get_etc_path():
    """
    :return:
    Returns etc directory path.
    """
    return os.path.join('C:', os.sep, 'Windows', 'System32', 'drivers', 'etc')


def build_popen_args(script):
    ## turn the script into utf16le, then to b64 again, and feed the blob to powershell
    u16 = script.encode ('utf-16le')                 ## utf16
    b64 = base64.b64encode (u16).decode ('utf-8')    ## b64 (which returns bytes, so we need an additional decode(utf8))
    return ['powershell', '-WindowStyle', 'Hidden', '-EncodedCommand', b64]
