## @file
# Replace distribution package.
#
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available 
# under the terms and conditions of the BSD License which accompanies this 
# distribution. The full text of the license may be found at 
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
"""
Replace a distribution package
"""
##
# Import Modules
#
from shutil import rmtree
from traceback import format_exc
from platform import python_version
from sys import platform
from Logger import StringTable as ST
from Logger.ToolError import UNKNOWN_ERROR
from Logger.ToolError import FatalError
from Logger.ToolError import ABORT_ERROR
from Logger.ToolError import CODE_ERROR
from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR
import Logger.Log as Logger

from Core.DependencyRules import DependencyRules
from Library import GlobalData
from InstallPkg import UnZipDp
from InstallPkg import InstallDp
from RmPkg import GetInstalledDpInfo
from RmPkg import RemoveDist

## Tool entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @param  Options: command Options
#
def Main(Options = None):
    ContentZipFile, DistFile = None, None
    try:
        DataBase = GlobalData.gDB
        WorkspaceDir = GlobalData.gWORKSPACE
        Dep = DependencyRules(DataBase)
        DistPkg, ContentZipFile, DpPkgFileName, DistFile = UnZipDp(WorkspaceDir, Options.PackFileToReplace)
        
        StoredDistFile, OrigDpGuid, OrigDpVersion = GetInstalledDpInfo(Options.PackFileToBeReplaced, \
                                                                       Dep, DataBase, WorkspaceDir)
        
        #
        # check dependency
        #
        CheckReplaceDpx(Dep, DistPkg, OrigDpGuid, OrigDpVersion)
        
        #
        # Remove the old distribution
        #
        RemoveDist(OrigDpGuid, OrigDpVersion, StoredDistFile, DataBase, WorkspaceDir, Options.Yes)
        
        #
        # Install the new distribution
        #
        InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase)
        ReturnCode = 0
        
    except FatalError, XExcept:
        ReturnCode = XExcept.args[0]
        if Logger.GetLevel() <= Logger.DEBUG_9:
            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
                platform) + format_exc())
    except KeyboardInterrupt:
        ReturnCode = ABORT_ERROR
        if Logger.GetLevel() <= Logger.DEBUG_9:
            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
                platform) + format_exc())
    except:
        ReturnCode = CODE_ERROR
        Logger.Error(
                    "\nReplacePkg",
                    CODE_ERROR,
                    ST.ERR_UNKNOWN_FATAL_REPLACE_ERR % (Options.PackFileToReplace, Options.PackFileToBeReplaced),
                    ExtraData=ST.MSG_SEARCH_FOR_HELP,
                    RaiseError=False
                    )
        Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
            platform) + format_exc())

    finally:
        Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED)
        if DistFile:
            DistFile.Close()
        if ContentZipFile:
            ContentZipFile.Close()
        if GlobalData.gUNPACK_DIR:
            rmtree(GlobalData.gUNPACK_DIR)
            GlobalData.gUNPACK_DIR = None
        Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE)        

    if ReturnCode == 0:
        Logger.Quiet(ST.MSG_FINISH)
    
    return ReturnCode

def CheckReplaceDpx(Dep, DistPkg, OrigDpGuid, OrigDpVersion):
    NewDpPkgList = []
    for PkgInfo in DistPkg.PackageSurfaceArea:
        Guid, Version = PkgInfo[0], PkgInfo[1]
        NewDpPkgList.append((Guid, Version))

    NewDpInfo = "%s %s" % (DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion())
    OrigDpInfo = "%s %s" % (OrigDpGuid, OrigDpVersion)

    #
    # check whether new distribution is already installed and not replacing itself
    #
    if (NewDpInfo != OrigDpInfo):
        if Dep.CheckDpExists(DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion()):
            Logger.Error("\nReplacePkg", UPT_ALREADY_INSTALLED_ERROR,
                ST.WRN_DIST_PKG_INSTALLED,
                ExtraData=ST.MSG_REPLACE_ALREADY_INSTALLED_DP)    

    #
    # check whether the original distribution could be replaced by new distribution
    #    
    Logger.Verbose(ST.MSG_CHECK_DP_FOR_REPLACE%(NewDpInfo, OrigDpInfo))
    DepInfoResult = Dep.CheckDpDepexForReplace(OrigDpGuid, OrigDpVersion, NewDpPkgList)
    Replaceable = DepInfoResult[0]
    if not Replaceable:
        Logger.Error("\nReplacePkg", UNKNOWN_ERROR,
            ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY)
    
    #
    # check whether new distribution could be installed by dependency rule
    #
    Logger.Verbose(ST.MSG_CHECK_DP_FOR_INSTALL%str(NewDpInfo))
    if not Dep.ReplaceCheckNewDpDepex(DistPkg, OrigDpGuid, OrigDpVersion):
        Logger.Error("\nReplacePkg", UNKNOWN_ERROR,
            ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY,
            ExtraData=DistPkg.Header.Name)

