## @file
# Setup the environment for unix-like systems running a bash-like shell.
# This file must be "sourced" not merely executed. For example: ". edksetup.sh"
#
# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016, Linaro Ltd. 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.
#

SetWorkspace() {

  #
  # If WORKSPACE is already set, then we can return right now
  #
  if [ -n "$WORKSPACE" ]
  then
    return 0
  fi

  #
  # Set $WORKSPACE
  #
  export WORKSPACE=`pwd`

  return 0

}

RestorePreviousConfiguration() {
  #
  # Restore previous configuration
  #
  if [ -z "$CONF_PATH" ]
  then
    export CONF_PATH=$WORKSPACE/Conf
    if [ ! -d $WORKSPACE/Conf ] && [ -n "$PACKAGES_PATH" ]
    then
      PATH_LIST=${PACKAGES_PATH//:/ }
      for DIR in $PATH_LIST
      do
        if [ -d $DIR/Conf ]
        then
          export CONF_PATH=$DIR/Conf
          break
        fi
      done
    fi
  fi
  
  PREVIOUS_CONF_FILE=$CONF_PATH/BuildEnv.sh
  if [ -e $PREVIOUS_CONF_FILE ]
  then
    echo Loading previous configuration from $PREVIOUS_CONF_FILE
    . $PREVIOUS_CONF_FILE
  fi
}

GenerateShellCodeToSetVariable() {
  VARIABLE=$1
  OUTPUT_FILE=$2
  VAR_VALUE="echo \${${VARIABLE}}"
  VAR_VALUE=`eval $VAR_VALUE`
  echo "if [ -z \"\$${VARIABLE}\" ]"             >> $OUTPUT_FILE
  echo "then"                                    >> $OUTPUT_FILE
  echo "  export ${VARIABLE}=${VAR_VALUE}"       >> $OUTPUT_FILE
  echo "fi"                                      >> $OUTPUT_FILE
}

GenerateShellCodeToUpdatePath() {
  OUTPUT_FILE=$1
  echo "if [ -e $EDK_TOOLS_PATH_BIN ]"                        >> $OUTPUT_FILE
  echo "then"                                                 >> $OUTPUT_FILE
  echo "  if [ "\${PATH/$EDK_TOOLS_PATH_BIN/}" == "\$PATH" ]" >> $OUTPUT_FILE
  echo "  then"                                               >> $OUTPUT_FILE
  echo "    export PATH=$EDK_TOOLS_PATH_BIN:\$PATH"           >> $OUTPUT_FILE
  echo "  fi"                                                 >> $OUTPUT_FILE
  echo "fi"                                                   >> $OUTPUT_FILE
}

StoreCurrentConfiguration() {
  #
  # Write configuration to a shell script to allow for configuration to be
  # easily reloaded.
  #
  OUTPUT_FILE=$CONF_PATH/BuildEnv.sh
  #echo Storing current configuration into $OUTPUT_FILE
  echo "# Auto-generated by ${BASH_SOURCE[0]}" >| $OUTPUT_FILE
  GenerateShellCodeToSetVariable WORKSPACE $OUTPUT_FILE
  GenerateShellCodeToSetVariable EDK_TOOLS_PATH $OUTPUT_FILE
  GenerateShellCodeToUpdatePath $OUTPUT_FILE
}

SetEdkToolsPath() {

  #
  # If EDK_TOOLS_PATH is already set, then we can return right now
  #
  if [ -n "$EDK_TOOLS_PATH" ]
  then
    return 0
  fi

  #
  # Try $CONF_PATH/EdkTools
  #
  if [ -e $CONF_PATH/EdkTools ]
  then
    export EDK_TOOLS_PATH=$CONF_PATH/EdkTools
    return 0
  fi

  #
  # Try $CONF_PATH/BaseToolsSource
  #
  if [ -e $CONF_PATH/BaseToolsSource ]
  then
    export EDK_TOOLS_PATH=$CONF_PATH/BaseToolsSource
    return 0
  fi

  #
  # Try $WORKSPACE/BaseTools
  #
  if [ -e $WORKSPACE/BaseTools ]
  then
    export EDK_TOOLS_PATH=$WORKSPACE/BaseTools
    return 0
  fi

  #
  # Try $PACKAGES_PATH
  #
  if [ -n "$PACKAGES_PATH"]
  then
    PATH_LIST=${PACKAGES_PATH//:/ }
    for DIR in $PATH_LIST
    do
      if [ -d $DIR/BaseTools ]
      then
        export EDK_TOOLS_PATH=$DIR/BaseTools
        return 0
      fi
    done
  fi

  echo "Unable to determine EDK_TOOLS_PATH"
  echo
  echo "You may need to download the 'BaseTools' from buildtools.tianocore.org."
  echo "After downloading, either create a symbolic link to the source at"
  echo "\$WORKSPACE/Conf/BaseToolsSource, or set the EDK_TOOLS_PATH environment"
  echo "variable."

}

GetBaseToolsBinSubDir() {
  #
  # Figure out a uniq directory name from the uname command
  #
  UNAME_DIRNAME=`uname -sm`
  UNAME_DIRNAME=${UNAME_DIRNAME// /-}
  UNAME_DIRNAME=${UNAME_DIRNAME//\//-}
  echo $UNAME_DIRNAME
}

GetEdkToolsPathBinDirectory() {
  #
  # Figure out a uniq directory name from the uname command
  #
  BIN_SUB_DIR=`GetBaseToolsBinSubDir`

  if [ -e $EDK_TOOLS_PATH/BinWrappers/$BIN_SUB_DIR ]
  then
    EDK_TOOLS_PATH_BIN=$EDK_TOOLS_PATH/BinWrappers/$BIN_SUB_DIR
  else
    EDK_TOOLS_PATH_BIN=$EDK_TOOLS_PATH/Bin/$BIN_SUB_DIR
  fi

  echo $EDK_TOOLS_PATH_BIN
}

AddDirToStartOfPath() {
  DIRNAME=$1
  PATH=$DIRNAME:$DIRNAME:$DIRNAME:$PATH
  PATH=${PATH//$DIRNAME:/}
  PATH=$DIRNAME:$PATH
  export PATH
}

AddEdkToolsToPath() {

  #
  # If EDK_TOOLS_PATH is not set, then we cannot update PATH
  #
  if [ -z "$EDK_TOOLS_PATH" ]
  then
    return 1
  fi

  EDK_TOOLS_PATH_BIN=`GetEdkToolsPathBinDirectory`

  AddDirToStartOfPath $EDK_TOOLS_PATH/BinWrappers/PosixLike
  AddDirToStartOfPath $EDK_TOOLS_PATH_BIN

}

CopySingleTemplateFile() {

  SRC_FILENAME=Conf/$1.template
  DST_FILENAME=$CONF_PATH/$1.txt

  if [ -e $DST_FILENAME ]
  then
    [ $RECONFIG != TRUE ] && return
  fi

  echo "Copying \$EDK_TOOLS_PATH/$SRC_FILENAME"
  echo "     to $DST_FILENAME"
  SRC_FILENAME=$EDK_TOOLS_PATH/$SRC_FILENAME
  cp $SRC_FILENAME $DST_FILENAME

}

CopyTemplateFiles() {

  CopySingleTemplateFile build_rule
  CopySingleTemplateFile tools_def
  CopySingleTemplateFile target

}

ScriptMain() {

  SetWorkspace
  if [ -z $WORKSPACE ]
  then
    echo "Failure setting WORKSPACE"
    return 1
  fi

  RestorePreviousConfiguration

  SetEdkToolsPath
  if [ -z $EDK_TOOLS_PATH ]
  then
    return 1
  fi

  AddEdkToolsToPath
  if [ $? -ne 0 ]
  then
    echo "Failure adding EDK Tools into PATH!"
    return 1
  fi

  StoreCurrentConfiguration

  echo WORKSPACE: $WORKSPACE
  echo EDK_TOOLS_PATH: $EDK_TOOLS_PATH
  echo CONF_PATH: $CONF_PATH

  CopyTemplateFiles

}

#
# Run the main function
#
ScriptMain

