#!/usr/bin/env bash

set -e

TAG_CJDNS=186169f9a8631633795e4e9d70c501519a7800f4

# Get board information and set flags accordingly
BOARD_FAMILY="Unknown"
BOARD_NAME="Generic"
BOARD_REVISION="?"
CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 ./do"
BOARD_HARDWARE=$(cat /proc/cpuinfo  | grep Hardware | awk '{print $3}' | head -n 1)

# Flag to identify if board can support on-board AP
SUPPORT_HOSTAP=false 

# Possibly use /sys/firmware/devicetree/base/model
if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; then   
    BOARD_FAMILY="Orange Pi"
    BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F \= '{print $2}' | tr -d \" | sed 's/Orange Pi //g')
    BOARD_REVISION="experimental"
    if [[ "$BOARD_NAME" == "Zero" ]]; then
        # AP is supported if board already supports XRadio
        if [ "$(lsmod | grep xradio_wlan)" ]; then 
            SUPPORT_HOSTAP=true
        fi
    fi
    CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-s -static -Wall -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -fomit-frame-pointer -marm\" ./do"
elif [[ "$BOARD_HARDWARE" == 'sun50iw1p1' ]]; then
    BOARD_FAMILY="Orange Pi"
    BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F \= '{print $2}' | tr -d \" | sed 's/Orange Pi //g')
    BOARD_REVISION="experimental"
    CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-s -static -Wall -march=armv8-a+crc+crypto -mcpu=cortex-a53 -ftree-vectorize -mtune=cortex-a53 -fomit-frame-pointer\" ./do"
else
    BOARD_FAMILY="Raspberry Pi"
    BOARD_REVISION=`sed -rn 's/Revision\s+\:\s+([0-9a-z_\-\s\,\(\)]+)/\1/p' /proc/cpuinfo`
    if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then
        BOARD_NAME="Zero"
        CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 CFLAGS=\"-s -static -Wall -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard\" ./do"
    elif [[ $BOARD_REVISION == *"00"* ]]; then
        BOARD_NAME="1"
        CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -static -Wall\" ./do"
    elif [[ $BOARD_REVISION == *"a01041"* || $BOARD_REVISION == *"a21041"* ]]; then
        BOARD_NAME="2"
        CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-s -static -Wall -mfpu=neon -mcpu=cortex-a7 -mtune=cortex-a7 -fomit-frame-pointer -marm\" ./do"
    elif [[ $BOARD_REVISION == *"a02082"* || $BOARD_REVISION == *"a22082"* ]]; then
        BOARD_NAME="3"
        CJDNS_BUILD_CMD="sudo CFLAGS=\"-march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard -O2\" ./do"

        # Raspberry Pi 3 has on-board WiFi that can be used as an AP
        SUPPORT_HOSTAP=true
    fi
fi

echo -e "\e[1;32mStarting installation on ${BOARD_FAMILY} ${BOARD_NAME} (${BOARD_REVISION})...\e[0m"

# Disable predictable network interface naming
sudo touch /etc/udev/rules.d/80-net-setup-link.rules

# Set configurations specific to the board
if [[ $BOARD_FAMILY == "Orange Pi" ]]; then
    # Downgrade kernel to enable XRadio in version 4.10 on Orange Pi Zero
    if ! [ -z "`uname -a | grep 4.11`" ]; then 
        if ! [ -z "`cat /sys/bus/mmc/devices/mmc1:0001/mmc1:0001:1/uevent | grep SDIO_ID | grep 0020:2281`" ]; then
            read -p "Downgrade kernel to enable XRadio on Orange Pi Zero (Y/n)? " -n 1 -r
            echo ""
            if ! [[ $REPLY =~ ^[Nn]$ ]]; then
                echo -e "\e[1;32mDowngrading Kernel...\e[0m"
                wget https://github.com/darkdrgn2k/OrangePiXRadio/raw/master/linux-image-dev-sun8i_5.26_armhf.deb 
                sudo dpkg -i linux-image-dev-sun8i_5.26_armhf.deb
                rm -rf linux-image-dev-sun8i_5.26_armhf.deb

                # AP supported on downgraded kernel
                SUPPORT_HOSTAP=true 
            else
                # AP not supported without kernel downgrade
                SUPPORT_HOSTAP=false 
            fi
        fi
    fi
fi

# Prompt and set missing flags
if [ -z "$WITH_MESH_POINT" -o "$WITH_MESH_POINT" != "true" -a "$WITH_MESH_POINT" != "false" ]; then
    read -p "Configure Mesh Point interface (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mMesh Point interface configuration will be skipped\e[0m"
        WITH_MESH_POINT=false
    else
        echo -e "\e[1;32mMesh Point interface will be configured\e[0m"
        WITH_MESH_POINT=true
    fi
fi
if [[ "$SUPPORT_HOSTAP" == "true" ]] && [ -z "$WITH_WIFI_AP" -o "$WITH_WIFI_AP" != "true" -a "$WITH_WIFI_AP" != "false" ]; then
    read -p "Configure WiFi Access Point (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mWiFi Access Point configuration will be skipped\e[0m"
        WITH_WIFI_AP=false
    else
        echo -e "\e[1;32mWiFi Access Point will be configured\e[0m"
        WITH_WIFI_AP=true
    fi
fi
if [ -z "$WITH_IPFS" -o "$WITH_IPFS" != "true" -a "$WITH_IPFS" != "false" ]; then
    read -p "Install IPFS (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mIPFS installation will be skipped\e[0m"
        WITH_IPFS=false
    else
        echo -e "\e[1;32mIPFS will be installed\e[0m"
        WITH_IPFS=true
    fi
fi
if [ -z "$WITH_PROMETHEUS_NODE_EXPORTER" -o "$WITH_PROMETHEUS_NODE_EXPORTER" != "true" -a "$WITH_PROMETHEUS_NODE_EXPORTER" != "false" ]; then
    read -p "Install Prometheus Node Exporter (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mPrometheus Node Exporter installation will be skipped\e[0m"
        WITH_PROMETHEUS_NODE_EXPORTER=false
    else
        echo -e "\e[1;32mPrometheus Node Exporter will be installed\e[0m"
        WITH_PROMETHEUS_NODE_EXPORTER=true
    fi
fi
if [ "$WITH_PROMETHEUS_NODE_EXPORTER" == true ]; then
    if [ -z "$WITH_PROMETHEUS_SERVER" -o "$WITH_PROMETHEUS_SERVER" != "true" -a "$WITH_PROMETHEUS_SERVER" != "false" ]; then
        read -p "Install Prometheus Server (Y/n)? " -n 1 -r
        echo ""
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            echo -e "\e[1;31mPrometheus installation will be skipped\e[0m"
            WITH_PROMETHEUS_SERVER=false
        else
            echo -e "\e[1;32mPrometheus Server will be installed\e[0m"
            WITH_PROMETHEUS_SERVER=true
        fi
    fi
else
    # Skip because Prometheus Node Exporter is not installed
    WITH_PROMETHEUS_SERVER=false
fi
if [ "$WITH_PROMETHEUS_SERVER" == true ]; then
    if [ -z "$WITH_GRAFANA" -o "$WITH_GRAFANA" != "true" -a "$WITH_GRAFANA" != "false" ]; then
        read -p "Install Grafana (Y/n)? " -n 1 -r
        echo ""
        if [[ $REPLY =~ ^[Nn]$ ]]; then
            echo -e "\e[1;31mGrafana installation will be skipped\e[0m"
            WITH_GRAFANA=false
        else
            echo -e "\e[1;32mGrafana will be installed\e[0m"
            WITH_GRAFANA=true
        fi
    fi
else
    # Skip because Prometheus Server is not installed
    WITH_GRAFANA=false
fi
if [ -z "$WITH_H_DNS" -o "$WITH_H_DNS" != "true" -a "$WITH_H_DNS" != "false" ]; then
    read -p "Configure Hyperboria-compatible Domain Name Servers (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mDNS settings will be skipped\e[0m"
        WITH_H_DNS=false
    else
        echo -e "\e[1;32mDNS settings will be configured\e[0m"
        WITH_H_DNS=true
    fi
fi
if [ -z "$WITH_H_NTP" -o "$WITH_H_NTP" != "true" -a "$WITH_H_NTP" != "false" ]; then
    read -p "Configure Hyperboria-compatible Network Time Protocol server (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mNTP settings will be skipped\e[0m"
        WITH_H_NTP=false
    else
        echo -e "\e[1;32mNTP settings will be configured\e[0m"
        WITH_H_NTP=true
    fi
fi
if [ -z "$WITH_FAKE_HWCLOCK" -o "$WITH_FAKE_HWCLOCK" != "true" -a "$WITH_FAKE_HWCLOCK" != "false" ]; then
    read -p "Configure Fake Hardware Clock to store time value every 5 minutes (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mFake Hardware Clock will be skipped\e[0m"
        WITH_FAKE_HWCLOCK_=false
    else
        echo -e "\e[1;32mFake Hardware Clock will be configured\e[0m"
        WITH_FAKE_HWCLOCK=true
    fi
fi
if [ -z "$WITH_EXTRA_TOOLS" -o "$WITH_EXTRA_TOOLS" != "true" -a "$WITH_EXTRA_TOOLS" != "false" ]; then
    read -p "Install non-essential tools useful for network analysis (Y/n)? " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        echo -e "\e[1;31mExtra tools will be skipped\e[0m"
        WITH_EXTRA_TOOLS=false
    else
        echo -e "\e[1;32mExtra tools will be installed\e[0m"
        WITH_EXTRA_TOOLS=true
    fi
fi

# Prompt for name of the mesh network
read -p "Enter the name of your mesh network (default: AtlMeshNet): " -r
export MESH_NAME=`echo $REPLY | sed 's/ //g'`
if [ "${#MESH_NAME}" == 0 ]; then
    export MESH_NAME="AtlMeshNet"
fi

# Get tools
if ! [ "$(which nodejs)" ]; then
    # Check for armv6 and install nodejs manually instead since it will not install via repo
    if $(uname -m | grep -Eq ^armv6); then
        wget -O /tmp/node-v6.11.0-linux-armv6l.tar.gz https://nodejs.org/dist/v6.11.0/node-v6.11.0-linux-armv6l.tar.gz
        sudo tar xfz /tmp/node-v6.11.0-linux-armv6l.tar.gz --strip 1 -C /
        rm -rf /tmp/node-v6.11.0-linux-armv6l.tar.gz
        sudo ln -s /bin/node /bin/nodejs
    else
       curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
       sudo apt-get install nodejs -y
   fi
fi

# Download cjdns repo and checkout TAG_CJDNS tag
if ! [ -d "/opt/cjdns" ]; then
    here=`pwd`
    sudo git clone https://github.com/cjdelisle/cjdns.git /opt/cjdns
    cd /opt/cjdns 
    sudo git checkout $TAG_CJDNS 
    cd $here
fi

# Build cjdns
if ! [ -x "/opt/cjdns/cjdroute" ]; then
    here=`pwd`
    cd /opt/cjdns && eval $CJDNS_BUILD_CMD && cd $here
fi

# Install cjdns to /usr/bin
sudo rm -f /usr/bin/cjdroute
sudo cp /opt/cjdns/cjdroute /usr/bin/cjdroute

# Generate cjdns configurations
if ! [ -f "/etc/cjdroute.conf" ]; then
    sudo /usr/bin/cjdroute --genconf | sudo tee --append /etc/cjdroute.conf > /dev/null
fi

# Configure systemd to start cjdns.service on system boot
sudo cp /opt/cjdns/contrib/systemd/cjdns.service /lib/systemd/system/cjdns.service
sudo chmod 644 /lib/systemd/system/cjdns.service
sudo cp /opt/cjdns/contrib/systemd/cjdns-resume.service /lib/systemd/system/cjdns-resume.service
sudo chmod 644 /lib/systemd/system/cjdns-resume.service
sudo systemctl daemon-reload
sudo systemctl enable cjdns.service

# 802.11s Mesh Point interface
if [ ! -z "$WITH_MESH_POINT" -a "$WITH_MESH_POINT" == "true" ]; then
    source mesh-point/install
fi

# WiFi Access Point on RPi3
if [[ "$SUPPORT_HOSTAP" == "true" ]] && [ ! -z "$WITH_WIFI_AP" -a "$WITH_WIFI_AP" == "true" ]; then
    source hostapd/install
fi

# IPFS
if [ ! -x "$(command -v ipfs)" ] && [ ! -z "$WITH_IPFS" -a "$WITH_IPFS" == "true" ]; then
    source ipfs/install
fi

# Prometheus Node Exporter
if [ ! -x "$(command -v node_exporter)" ] && [ ! -z "$WITH_PROMETHEUS_NODE_EXPORTER" -a "$WITH_PROMETHEUS_NODE_EXPORTER" == "true" ]; then
    source prometheus-node-exporter/install
fi

# Prometheus Server
if [ ! -x "$(command -v /opt/prometheus/prometheus)" ] && [ ! -z "$WITH_PROMETHEUS_SERVER" -a "$WITH_PROMETHEUS_SERVER" == "true" ]; then
    source prometheus-server/install
fi

# Grafana
if [ ! -x "$(command -v /usr/sbin/grafana-server)" ] && [ ! -z "$WITH_GRAFANA" -a "$WITH_GRAFANA" == "true" ]; then
    source grafana/install
fi

# Configure Hyperboria DNS
if [ ! -z "$WITH_H_DNS" -a "$WITH_H_DNS" == "true" ]; then
    source h-dns/install
fi

# Configure Hyperboria NTP
if [ ! -z "$WITH_H_NTP" -a "$WITH_H_NTP" == "true" ]; then
    source h-ntp/install
fi

# Configure Fake Hardware Clock
if [ ! -z "$WITH_FAKE_HWCLOCK" -a "$WITH_FAKE_HWCLOCK" == "true" ]; then
    source fake-hwclock/install
fi

# Non-essential extra tools
if [ ! -z "$WITH_EXTRA_TOOLS" -a "$WITH_EXTRA_TOOLS" == "true" ]; then
    source extra-tools/install
fi

# Install node status script
sudo cp status /usr/local/bin/status
echo -e "Run \e[1;32mstatus\e[0m anytime to print the status of your node"

# Print node status on login
cp ~/.profile ~/.bash_profile
echo "" >> ~/.bash_profile
echo "# export mesh network name" >> ~/.bash_profile
echo "export MESH_NAME=$MESH_NAME" >> ~/.bash_profile
echo "" >> ~/.bash_profile 
echo "# print mesh node status" >> ~/.bash_profile
echo "status" >> ~/.bash_profile

# Reboot device
sudo reboot
