#! /bin/sh
#
#   Copyright (c) 2015 Nat! - Mulle kybernetiK
#   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 Mulle kybernetiK 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.

MULLE_BOOTSTRAP_VERSION="2.1"

#
# This is the main user interface to mulle-bootstrap
# sorta like git
#

trap_fail()
{
   exit 1
}


usage()
{
   cat <<EOF
usage: mulle-bootstrap [options] [command] [--help]
 Common Options:
   -a -y     : default answer to questions (scripts wont be checked)
               -a (clone preferred) -y (local copy/symlink preferred)
   -n        : do nothing creative or destructive
   -v        : -v to be more verbose (-vv or -vvv for more verbosity)
   -V        : show build commands

 Common user commands:
   bootstrap : does fetch and build recursively [default]
   clean     : cleans mulle-bootstrap produced files.

 Common maintainer commands:
   init      : initializes a bootstrap project
EOF

   if [ "${UNAME}" = 'darwin' ]
   then
      cat <<EOF
   xcode     : sets up xcodeproj settings
EOF
   fi

cat <<EOF
   tag       : tag this project and fetched repositories

 Specialized commands:
   build     : builds fetched repositories
   fetch     : fetches required repositories recursively. Use it after updating
               the repositories and embedded_repositories files.
   update    : updates repositories (pull).
   install   : install dependencies as system headers
EOF
   exit 1
}


ensure_consistency()
{
   local owd

   owd="`pwd -P`"

   if [ -f "${CLONESFETCH_SUBDIR}/.fetch_update_started" ]
   then
      log_error "A previous fetch or update was incomplete.
Suggested resolution (in $owd):
    ${C_RESET_BOLD}mulle-bootstrap clean dist${C_ERROR}
    ${C_RESET_BOLD}mulle-bootstrap${C_ERROR}

Or do you feel lucky ? Then try again with
   ${C_RESET_BOLD}mulle-bootstrap -f${C_ERROR}
But you've gotta ask yourself one question: Do I feel lucky ?
Well, do ya, punk?"
      exit 1
   fi
}


bootstrap_nomagic_main()
{
   local command

   command="$1"
   shift

   if [ "${command}" = "nomagic" ]
   then
      DONT_RECURSE=YES
   fi

   . mulle-bootstrap-fetch.sh
   . mulle-bootstrap-build.sh
   . mulle-bootstrap-warn-scripts.sh

   [ -z "${MULLE_BOOTSTRAP_REFRESH_SH}" ] && . mulle-bootstrap-refresh.sh

   # used for option handling only
   MULLE_BOOTSTRAP_WILL_BUILD="YES"

   warn_scripts_main "${BOOTSTRAP_SUBDIR}" || exit 1

   if fetch_needed
   then
      if [ -z "${DONT_RECURSE}" ]
      then
         fetch_main "$@" || exit 1
         refresh_main    || exit 1
      else
         fetch_main --non-recursive "$@" || exit 1
         refresh_main nonrecursive       || exit 1
      fi
      # used for option handling only
      MULLE_BOOTSTRAP_DID_FETCH="YES"
   fi

   if build_needed
   then
      build_main "$@" || exit 1
   fi
}


bootstrap_main()
{
   local command

   BOOTSTRAP_SUBDIR=.bootstrap

   PATH="/usr/local/libexec/mulle-bootstrap:`pwd -P`/dependencies/bin:`pwd -P`/addictions/bin:$PATH"
   export PATH

   #
   # shell export commands with minimal
   # trap setup
   #
   case "${1}" in
      library-path)
         echo "$PATH" | tr ':' '\012' | head -1
         exit 0
      ;;

      version)
         echo "${MULLE_BOOTSTRAP_VERSION}"
         exit 0
      ;;
   esac

   MULLE_BOOTSTRAP_PID="$$"
   export MULLE_BOOTSTRAP_PID

   # now include this first to get
   # logging and UNAME

   . mulle-bootstrap-logging.sh
   . mulle-bootstrap-local-environment.sh

   trap trap_fail INT

   #
   # simple option handling
   #
   while [ $# -ne 0 ]
   do
      case "$1" in
         -a|--prefer-origin)
            MULLE_BOOTSTRAP_ANSWER="NO"
          ;;

         -y|--prefer-local)
            MULLE_BOOTSTRAP_ANSWER="YES"
         ;;

         -c|--check-usr-local-include)
            MULLE_BOOTSTRAP_CHECK_USR_LOCAL_INCLUDE="YES"
         ;;

         -f|--force-fetch)
            MULLE_BOOTSTRAP_DIRTY_HARRY="NO"
         ;;

         -fr|--force-refresh)
            MULLE_BOOTSTRAP_NEEDS_REFRESH="YES"
         ;;

         -n|--dry-run)
            MULLE_EXECUTOR_DRY_RUN="YES"
         ;;

         -l|--optimistic|--lucky)
            MULLE_BOOTSTRAP_OPTIMISTIC="YES"
         ;;

         -ig|--ignore-graveyard)
            MULLE_BOOTSTRAP_IGNORE_GRAVEYARD="YES"
         ;;

         -te|--trace-execution)
            MULLE_EXECUTOR_TRACE="YES"
         ;;

         -tm|--trace-settings-merge)
            MULLE_BOOTSTRAP_TRACE_MERGE="YES"
         ;;

         -ts|--trace-scripts)
            MULLE_BOOTSTRAP_TRACE_SCRIPT_CALLS="YES"
         ;;

         -tt|--trace-ignores-settings)
            MULLE_BOOTSTRAP_SETTINGS_FLIP_X="YES"
         ;;

         -tp|--trace-ignores-paths)
            MULLE_BOOTSTRAP_PATHS_FLIP_X="YES"
         ;;

         -t|--trace)
            MULLE_BOOTSTRAP_TRACE="1848"
            COPYMOVEFLAGS="-v"
            GITFLAGS="${GITFLAGS} -v"
         ;;

         -V|--verbose-build)
            MULLE_BOOTSTRAP_VERBOSE_BUILD="YES"
         ;;

         -v|--verbose)
            MULLE_BOOTSTRAP_TRACE="VERBOSE"
            COPYMOVEFLAGS="-v"
            GITFLAGS="${GITFLAGS} -v"
         ;;

         -vv|--very-verbose)
            MULLE_BOOTSTRAP_TRACE="FLUFF"
            COPYMOVEFLAGS="-v"
            GITFLAGS="${GITFLAGS} -v"
         ;;

         -vvv|--very-verbose-with-settings)
            MULLE_BOOTSTRAP_TRACE="TRACE"
            COPYMOVEFLAGS="-v"
            GITFLAGS="${GITFLAGS} -v"
         ;;

         -s|--silent)
            MULLE_BOOTSTRAP_TRACE=
            MULLE_BOOTSTRAP_TERSE="YES"
            GITFLAGS="${GITFLAGS} -q"
         ;;

         -h|--help)
            usage
         ;;

         -*)
            log_error "unknown option \"$1\""
            usage
         ;;

         *)
            break
         ;;
      esac

      shift
   done

   case "${MULLE_BOOTSTRAP_TRACE}" in
      VERBOSE)
         MULLE_BOOTSTRAP_FLUFF="NO"
         MULLE_BOOTSTRAP_VERBOSE="YES"
         if [ -z "${MULLE_BOOTSTRAP_VERBOSE_BUILD}" ]
         then
            MULLE_BOOTSTRAP_VERBOSE_BUILD="NO"
         fi
      ;;

      FLUFF)
         MULLE_BOOTSTRAP_FLUFF="YES"
         MULLE_BOOTSTRAP_VERBOSE="YES"
         MULLE_EXECUTOR_TRACE="YES"
         if [ -z "${MULLE_BOOTSTRAP_VERBOSE_BUILD}" ]
         then
            MULLE_BOOTSTRAP_VERBOSE_BUILD="NO"
         fi
      ;;

      TRACE)
         MULLE_BOOTSTRAP_TRACE_SETTINGS="YES"
         MULLE_EXECUTOR_TRACE="YES"
         MULLE_BOOTSTRAP_FLUFF="YES"
         MULLE_BOOTSTRAP_VERBOSE="YES"
         if [ -z "${MULLE_BOOTSTRAP_VERBOSE_BUILD}" ]
         then
            MULLE_BOOTSTRAP_VERBOSE_BUILD="NO"
         fi
         log_trace "FULL trace started"
      ;;

      1848)
         MULLE_BOOTSTRAP_TRACE_SETTINGS="NO"
         MULLE_EXECUTOR_TRACE="NO"
         MULLE_BOOTSTRAP_FLUFF="NO"
         MULLE_BOOTSTRAP_VERBOSE="NO"
         if [ -z "${MULLE_BOOTSTRAP_VERBOSE_BUILD}" ]
         then
            MULLE_BOOTSTRAP_VERBOSE_BUILD="YES"
         fi
         log_trace "1848 trace (set -x) started"
         set -x
      ;;
   esac

   if [ "${MULLE_EXECUTOR_DRY_RUN}" = "YES" ]
   then
      log_trace "Dry run is active."
   fi

   #
   # some commands only run when we have a .bootstrap folder
   #
   command=${1:-"bootstrap"}
   [ $# -eq 0 ] || shift

   if [ ! -d "${BOOTSTRAP_SUBDIR}" ]
   then
      case "${command}" in
         bootstrap|nomagic|build|ibuild|refresh|dist|clean|dist-clean|fetch|update|setup-xcode|xcode|tag)
            fail "There is no ${BOOTSTRAP_SUBDIR} folder here, can't continue"
      esac
   fi

   if [ "${MULLE_BOOTSTRAP_DIRTY_HARRY}" != "NO" ]
   then
      case "${command}" in
         clean|dist-clean|init)
            :
         ;;
         *)
            ensure_consistency
         ;;
      esac
   fi

   #
   # some commands should refresh before execution
   # try to avoid pulling in the header if not needed
   #
   if [ "${MULLE_BOOTSTRAP_NEEDS_REFRESH}" = "YES" ] || refresh_needed
   then
      case "${command}" in
         bootstrap|nomagic|fetch)
            MULLE_BOOTSTRAP_WILL_FETCH="YES"
            . mulle-bootstrap-refresh.sh
            refresh_main || exit 1
         ;;

         setup-xcode|xcode|tag)
           . mulle-bootstrap-refresh.sh
            refresh_main || exit 1
         ;;

         build)
           . mulle-bootstrap-refresh.sh

            refresh_main refresh_if_bare || exit 1
         ;;

         update|refresh)
           . mulle-bootstrap-refresh.sh

           # 4 laters
         ;;
      esac
   fi

   case "${command}" in
      bootstrap|nomagic)
         bootstrap_nomagic_main "${command}" "$@"
      ;;

      build)
         . mulle-bootstrap-build.sh

         build_main "$@" || exit 1
      ;;

      clean)
         . mulle-bootstrap-clean.sh

         clean_main "$@" || exit 1
      ;;

      config)
         . mulle-bootstrap-settings.sh
         config_main "$@" || exit 1
      ;;

      dist)
         . mulle-bootstrap-clean.sh

         clean_main "dist" || exit 1
      ;;

      fetch)
         . mulle-bootstrap-fetch.sh

         DONT_ASK_AFTER_WARNING=YES fetch_main "$@" || exit 1
         refresh_main || exit 1
      ;;

      init)
         . mulle-bootstrap-init.sh

         init_main "$@" || exit 1
      ;;

      install)
         . mulle-bootstrap-install.sh

         install_main "$@" || exit 1
      ;;

      library-path)
         echo "$PATH" | tr ':' '\012' | head -1
         exit 0
      ;;

      refresh)
         [ -z "${MULLE_BOOTSTRAP_REFRESH_SH}" ] && . mulle-bootstrap-refresh.sh

         refresh_main "$@" || exit 1
      ;;

      update|pull)
         . mulle-bootstrap-fetch.sh

         update_main "$@" || exit 1

         [ -z "${MULLE_BOOTSTRAP_REFRESH_SH}" ] && . mulle-bootstrap-refresh.sh
         refresh_main || exit 1
      ;;

      setup-xcode|xcode)
         . mulle-bootstrap-xcode.sh

         xcode_main "$@" || exit 1
      ;;

      tag)
         . mulle-bootstrap-tag.sh

         tag_main "$@" || exit 1
      ;;

      git)
         . mulle-bootstrap-scm.sh

         git_main "$@" || exit 1
      ;;

      version)
         echo "${MULLE_BOOTSTRAP_VERSION}" || exit 1
      ;;

      *)
         log_error "Unknown command \"${command}\""
         usage
      ;;
   esac
}

bootstrap_main "$@"