#!/bin/bash
# Set parameters



DOWNLOAD_DIR="http://dl.fogworks.io/maxio/online"
LOG_DIR="/var/log"
LOG_FILE="$LOG_DIR/maxio_install.log"
VERSION_DIR="/opt/.maxio_version/"
DIRS=("$VERSION_DIR")
InstallPath="/opt"
InstallPacketPath="$InstallPath/facmgr_install_maxio.tar.bz2"
VFS_DIR="$DATADIR/vfs"

declare -A packages=(

    ["facmgr"]="1.0.1"
    ["sensor-data"]="1.0.1"
    ["sensor"]="1.0.1"

)



COMPOSE_DIR="/opt/facmgr/service"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose-vault.yml"

storage_services=("prox_mpd")


file_name=""

upgrade=false
reinstall=false

function log {
    echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" | tee -a $LOG_FILE
}


while getopts ":fur" opt; do
  case $opt in
    u)
      upgrade=true
      ;;
    r)
      reinstall=true
      ;;
    f)
      file_name="$OPTARG"
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

if [ "$reinstall" = true ]; then
  log "Reinstall is set to true."
else
  log "Reinstall is set to false."
fi

if [ "$upgrade" = true ]; then
  log "Upgrade is set to true."
else
  log "Upgrade is set to false."
fi




if [ -n "$file_name" ]; then
  file="$VERSION_DIR/$file_name"

  if [ ! -f "$file" ]; then
    echo "Error: File $file not found."
    exit 1
  fi

  while read -r package version; do
    packages["$package"]="$version"
  done < "$file"
fi



if [ "$upgrade" = true ] && [ "$reinstall" = true ]; then
    log "The parameter is incorrect"
    exit
fi


upgrade_flag=""
if [ "$upgrade" = true ]; then
  upgrade_flag="-u"
fi



check_root() {
  if [[ $EUID -ne 0 ]]; then
    log "This script must be run as root"
    exit 1
  fi
}


create_directory() {
  local dir="$1"
  if [ ! -d "$dir" ]; then
    log "Directory $dir does not exist. Creating..."
    mkdir -p "$dir" || {
      log "Failed to create directory $dir"
      exit 1
    }
  fi
}

create_log() {

  if [ ! -f "$LOG_FILE" ]; then
    touch "$LOG_FILE"
  fi

}


unmount_directory() {
  local mount_point
  mount_point=$(df -P "$VFS_DIR" | awk 'END{print $NF}')
  if [ "$VFS_DIR" = "$mount_point" ]; then
    echo "Directory $VFS_DIR is a mount point. Unmounting..."
    if ! umount -l "$VFS_DIR"; then
      echo "Failed to unmount directory $VFS_DIR"
      exit 1
    fi
  fi
  umount $VFS_DIR 2>/dev/null || true
  echo "Directory $VFS_DIR is a mount point. Unmounting..."
}



upgrade_storage_service() {
    for service in "${storage_services[@]}"; do
        if docker-compose -f "$COMPOSE_FILE" ps -q "$service" &>/dev/null; then

            #current_image_sha=$(docker inspect --format='{{.Id}}' "$(docker-compose -f "$COMPOSE_FILE" images -q "$service")")
            image_name=$(grep -A 5 "$service:" $COMPOSE_FILE | grep "^\s*image:" | awk '{print $2}')
            current_image_sha=$(docker inspect --format='{{.Id}}' "$image_name")

            timeout 300 docker-compose -f "$COMPOSE_FILE" pull "$service" >> "$LOG_FILE" 2>&1

            if [ $? -ne 0 ]; then
              log "Failed to pull image with timeout"
              return 1 
            fi


            docker-compose -f "$COMPOSE_FILE" pull "$service" >> "$LOG_FILE" 2>&1
            updated_image_sha=$(docker inspect --format='{{.Id}}' "$image_name")
            
            log "image_name is $image_name, $service current_image_sha is $current_image_sha,updated_image_sha is $updated_image_sha"
            if [ "$current_image_sha" != "$updated_image_sha" ]; then
                docker stop "$service" >> "$LOG_FILE" 2>&1
                docker rm "$service" >> "$LOG_FILE" 2>&1
                docker image prune -f >> "$LOG_FILE" 2>&1
                docker-compose -f "$COMPOSE_FILE" up -d --force-recreate "$service" >> "$LOG_FILE" 2>&1
                log "Container for service $service has been recreated."
            else
                log "No updates found for service $service. Container remains unchanged."
            fi
        else
            log "Container for service $service is not running. Skipping update and recreation for this service."
        fi
    done
}



facmgr_install() {

    local version=$1


    if [ "$upgrade_flag" = "-u" ]; then
      log "Currently upgrading: facmgr_${version}"
    else
      log "Currently installing: facmgr_${version}"
    fi

    if [ -z "$version" ]; then
      curl $DOWNLOAD_DIR/facmgr/install_facmgr.sh|bash -s -- $upgrade_flag
    else
      curl $DOWNLOAD_DIR/facmgr/install_facmgr.sh|bash -s -- -v $version $upgrade_flag
    fi

    if [ -f "$InstallPacketPath" ]; then
      existing_md5=$(md5sum "$InstallPacketPath" | cut -d' ' -f1)
      remote_md5=$(curl -s $DOWNLOAD_DIR/facmgr/facmgr_install_md5 | awk '{print $1}')


      if [ "$existing_md5" = "$remote_md5" ]; then
        log "facmgr_install_maxio.tar.bz2 file already exists and has the same MD5. No need to download."
      else
        rm -rf $InstallPacketPath
        wget "$DOWNLOAD_DIR/facmgr/facmgr_install_maxio.tar.bz2" -P "$InstallPath"
        log "New facmgr_install_maxio.tar.bz2 file downloaded."
        download=true
      fi
    else
      wget "$DOWNLOAD_DIR/facmgr/facmgr_install_maxio.tar.bz2" -P "$InstallPath"
      log "File facmgr_install_maxio.tar.bz2 downloaded."
    fi


    if [ "$download" = true ]; then
            tar -xf $InstallPacketPath -C $InstallPath    
            if [ -f "/opt/facmgr_install/upgrade.sh" ]; then
              bash /opt/facmgr_install/upgrade.sh
            fi
    fi

}


system_service() {

    version_file="$VERSION_DIR/$(date +'%Y%m%d%H%M%S').txt"
    for package_name in "${!packages[@]}"; do
      version="${packages[$package_name]}"
      if [ "$package_name" = "facmgr" ]; then
        facmgr_install ${version}
        echo "$package_name $version" >> "$version_file"
      else
        InstallPacketPath=/opt/${package_name}_${version}.tar.bz2
        download=false
        url="$DOWNLOAD_DIR/${package_name}/${package_name}_${version}.tar.bz2"
        if [ -f "$InstallPacketPath" ]; then
          if [ "$reinstall" = true ]; then
              if [ -f "/opt/${package_name}_${version}/uninstall.sh" ]; then
                cd /opt/${package_name}_${version} && bash uninstall.sh 
              fi
          fi

          existing_md5=$(md5sum "$InstallPacketPath" | cut -d' ' -f1)
          remote_md5=$(curl -s "$DOWNLOAD_DIR/${package_name}/${package_name}_${version}_md5" | awk '{print $1}')

          log "${package_name}_${version} Existing MD5: $existing_md5, Remote MD5: $remote_md5"
          if [ "$existing_md5" = "$remote_md5" ]; then
            log "${package_name}_${version} File already exists and has the same MD5. No need to download."
          else
            rm -rf $InstallPacketPath
            log "Downloading $url to /opt"
            wget -O "$InstallPacketPath" "$url"
            download=true
          fi
        else
          log "Downloading $url to /opt"
          wget -O "$InstallPacketPath" "$url"
          download=true
        fi

        InstallDir="/opt/${package_name}_${version}"
        if [ "$download" = true ]; then
          if [ -d $InstallDir ]; then
            rm -r $InstallDir
            log "Old ${package_name}_${version} Packet dir removed."
          fi
        fi

        if [ ! -d $InstallDir ]; then
          tar -jxvf "/opt/${package_name}_${version}.tar.bz2" -C /opt

        fi

        if [ "$download" = true ]; then

          if [ -f "/opt/${package_name}_${version}/install.sh" ]; then
            if [ "$upgrade_flag" = "-u" ]; then
              if [ -f "/opt/${package_name}_${version}/upgrade.sh" ]; then
                log "Currently upgrading: ${package_name}_${version}"
                cd /opt/${package_name}_${version} && bash upgrade.sh -s -- $upgrade_flag
              else
                log "Upgrade script not found for ${package_name}_${version}. Skipping upgrade."
              fi

            else
              log "Currently installing: ${package_name}_${version}"
              cd /opt/${package_name}_${version} && bash install.sh -s -- $upgrade_flag
            fi

            echo "$package_name $version" >> "$version_file"
          else
            log "No install.sh found for $package_name. Skipping installation."
          fi

        fi

      fi
    done

}



cron_upgrade() {

    command_to_run="curl $DOWNLOAD_DIR/install_maxio.sh | bash -s - -u"
    logfile="/var/log/maxio_cron.log"

    existing_cron=$(crontab -l 2>/dev/null)
    if [[ $existing_cron == *"curl $DOWNLOAD_DIR"* ]]; then
        new_cron=$(echo "$existing_cron" | grep -v "install_maxio.sh")
        echo "$new_cron" | crontab -
        log "Existing cron job(s) with '$command_to_run' removed"
    fi

    (crontab -l 2>/dev/null; echo "0 0 * * * $command_to_run >> $logfile 2>&1") | crontab -
    echo "New cron job added: $command_to_run"
    /usr/sbin/service cron restart

}


function is_package_installed() {
    if dpkg -s $1 >/dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

function install_package() {
    MAX_RETRIES=3
    RETRIES=0

    if ! is_package_installed $1; then
        while [ $RETRIES -lt $MAX_RETRIES ]; do
            log "Installing $1..."
            apt-get install -y $1
            if [ $? -eq 0 ]; then
                log "$1 successfully installed."
                break
            else
                RETRIES=$((RETRIES + 1))
                log "Failed to install $1. Retrying... (Attempt $RETRIES)"
            fi
        done

        if [ $RETRIES -eq $MAX_RETRIES ]; then
            log "Failed to install $1 after $MAX_RETRIES attempts. Please check your network connection and try again."
            exit 1
        fi
    else
        log "$1 is already installed. Skipping..."
    fi
}



function install_docker {

    apt install -y apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release

    rm -f /usr/share/keyrings/docker-archive-keyring.gpg
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    apt update -y

}


package_install(){
  if [ -f /var/lib/dpkg/lock ]; then
    rm /var/lib/dpkg/lock
  fi
  dpkg --configure -a

  if ! dpkg -s docker-ce &>/dev/null; then
    install_docker
    install_package docker-ce
    check_command "docker-ce"
  fi

  if ! dpkg -s docker-compose &>/dev/null; then
    install_package docker-compose
    check_command "docker-compose"
  fi

  if ! dpkg -s bzip2 &>/dev/null; then
    install_package bzip2
    check_command "bzip2"
  fi

  if ! dpkg -s lbzip2 &>/dev/null; then
    install_package lbzip2
    check_command "lbzip2"
  fi

  if ! dpkg -s iw &>/dev/null; then
    install_package iw
    check_command "iw"
  fi

  if ! dpkg -s dnsmasq &>/dev/null; then
    install_package dnsmasq
    check_command "dnsmasq"
  fi

  if ! dpkg -s hostapd &>/dev/null; then
    install_package hostapd
    check_command "hostapd"
  fi
  
}

function check_command {
  if [ $? -eq 0 ]; then
    log "$1 successfully installed."
  else
    log "Failed to install $1. Please check your network connection and try again."
    exit 1
  fi
}


main() {
  check_root
  create_log
  for dir in "${DIRS[@]}"; do
    create_directory "$dir"
  done
  package_install
  system_service
  if [ "$upgrade_flag" = "-u" ]; then
    upgrade_storage_service
  fi
  cron_upgrade
}

main
log "MAX IO system initialization module installation completed."
