#!/bin/bash

###########################################################
# Website Architecture Server Setup                       #
# ---------------------------------                       #
# By Mike Serritella                                      #
#                                                         #
# This builds the Website Architecture server environment #
# within an Ubuntu-based home operating system. Server    #
# flavors of the OS are not needed, and variants such as  #
# Kubuntu and Xubuntu may be used; Xubuntu is recommended #
# for its low use of resources and compatibility with     #
# Ubuntu in general.                                      #
#                                                         #
# This installs packages, creates a folder in the         #
# executing user's home directory, writes scripts that    #
# help to intuitively use the installed software, and     #
# modifies the PATH environment variable to bring those   #
# scripts into scope.                                     #
#                                                         #
# This file is cleanly written and may be inspected for   #
# comprehension.                                          #
#                                                         #
###########################################################

# VARIABLES
###########

OSUser="$USER"
HomeDirectory=`dirname "$HOME"`'/'`basename "$HOME"`'/'
WAMDirectory="$HomeDirectory"'WAM/'
ScriptsDirectory="$HomeDirectory"'WAM/Scripts/'
ServerDirectory="$HomeDirectory"'WAM/Server/'
ServerHTMLDirectory="$HomeDirectory"'WAM/Server/public_html/'

DefaultServerDirectoryNoSlash='/var/www'
DefaultServerDirectory="$DefaultServerDirectoryNoSlash"'/'

# FUNCTIONS
###########

# Utility functions
#==================

# Creates a bash script, including writing it to a given
# location and setting it as executable.
#  $1: Script path
#  $2+: Script contents, one parameter per line up
#       to a maximum of 9 lines, without #! line
function CreateScript {
    # Save the file path.
    ScriptPath="$1"

    # Create the file.
    touch "$ScriptPath"

    # Set the file as executable.
    chmod ugo+x "$ScriptPath"

    # Overwrite any existing data, and write the #! line.
    echo '#! /bin/bash' > "$ScriptPath"

    # Write a newline.
    echo '' >> "$ScriptPath"

    # Shift past the 1st parameter, so that after this,
    # all the parameters from $1 are the script lines.
    shift 1

    # Write the script contents.
    if [ $# -gt 0 ]; then
        echo $1 >> "$ScriptPath"
    fi
    if [ $# -gt 1 ]; then
        echo $2 >> "$ScriptPath"
    fi
    if [ $# -gt 2 ]; then
        echo $3 >> "$ScriptPath"
    fi
    if [ $# -gt 3 ]; then
        echo $4 >> "$ScriptPath"
    fi
    if [ $# -gt 4 ]; then
        echo $5 >> "$ScriptPath"
    fi
    if [ $# -gt 5 ]; then
        echo $6 >> "$ScriptPath"
    fi
    if [ $# -gt 6 ]; then
        echo $7 >> "$ScriptPath"
    fi
    if [ $# -gt 7 ]; then
        echo $8 >> "$ScriptPath"
    fi
    if [ $# -gt 8 ]; then
        echo $9 >> "$ScriptPath"
    fi
}

# Creates a bash script, as in CreateScript, but also creates
# a symlink to the script with a lowercase filename.
#  $1: Script path
#  $2+: Script contents, one parameter per line up
#       to a maximum of 9 lines, without #! line
function CreateScriptAndLowercaseAlias {
    # Save the name and directory of the script file;
    # compute the lowercase equivalent of the filename.
    ParameterScriptName=`basename "$1"`
    ParameterScriptNameInLowercase=`echo "$ParameterScriptName" | tr '[A-Z]' '[a-z]'`
    ParameterScriptDirectory=`dirname "$1"`

    # Create the script.
    CreateScript "$@"

    # Save the current directory.
    pushd &> /dev/null

    # Change directories to that of the script.
    cd "$ParameterScriptDirectory"

    # Create a symlink with a lowercase name.
    ln -s "$ParameterScriptName" "$ParameterScriptNameInLowercase" &> /dev/null

    # Restore the prior working directory.
    popd &> /dev/null
}

# Environment-modification functions
#===================================

# Creates the directories of the server and the script files
# for use throughout the script and by the OS user.
function CreateWAMDirectories {
    echo ' Creating directories for scripts and for the server.'
    echo ' They will all be within '"$WAMDirectory"
    echo
    sleep 0.5

    mkdir "$WAMDirectory" &> /dev/null
    mkdir "$ScriptsDirectory" &> /dev/null
    mkdir "$ServerDirectory" &> /dev/null
    mkdir "$ServerHTMLDirectory" &> /dev/null
}

# Modifies the PATH environment variable to include the new
# scripts directory.
function ModifyPathEnvironmentVariable {
    echo ' Adding the new scripts directory to the path.'
    echo
    sleep 0.5
    
    echo '' >> "$HomeDirectory"'.profile'
    echo 'PATH='"$PATH"':'"$ScriptsDirectory" >> "$HomeDirectory"'.profile'
}

# Modifies the environment and filesystem according to the
# requirements of the server.
function ModifyEnvironmentAndFilesystem {
    # Declare intent.
    echo
    echo ' ===================================='
    echo ' MODIFYING Environment AND Filesystem'
    echo ' ===================================='
    echo

    CreateWAMDirectories

    ModifyPathEnvironmentVariable
}

# Package-installation functions
#===============================

# Installs the packages necessary for the server.
function InstallPackages {
    # Declare intent.
    echo
    echo ' ===================='
    echo ' INSTALLING PACKAGES.'
    echo ' ===================='
    echo
    sleep 3

    # Update the package repository.
    echo '  Updating the package repository.'
    sleep 0.5
    sudo apt-get update &> /dev/null

    # Install Apache HTTP Server, version 2.
    echo
    echo
    echo '  Installing Apache HTTP Server, version 2 (latest).'
    echo '  --------------------------------------------------'
    echo
    sleep 2
    sudo apt-get install apache2

    # Install PHP 5 for the server.
    echo
    echo
    echo '  Installing PHP 5 (latest) for the server.'
    echo '  -----------------------------------------'
    echo
    sleep 2
    sudo apt-get install php5

    # Install PHP 5 for the command line.
    echo
    echo
    echo '  Installing PHP 5 (latest) for the command line.'
    echo '  -----------------------------------------------'
    echo
    sleep 2
    sudo apt-get install php5-cli

    # Install PostgreSQL.
    echo
    echo
    echo '  Installing PostgreSQL server (latest).'
    echo '  --------------------------------------'
    echo
    sleep 2
    sudo apt-get install postgresql

    # Install pgAdmin III.
    echo
    echo
    echo '  Installing pgAdmin III (latest).'
    echo '  --------------------------------'
    echo
    sleep 2
    sudo apt-get install pgadmin3

    # Install phpPgAdmin.
    echo
    echo
    echo '  Installing phpPgAdmin (latest).'
    echo '  -------------------------------'
    echo
    sleep 2
    sudo apt-get install phppgadmin

    # Install MySQL.
    echo
    echo
    echo '  Installing MySQL server (latest).'
    echo '  You may be asked for new passwords and options;'
    echo '    you can just press <Enter> for everything.'
    echo '  -----------------------------------------------'
    echo
    sleep 2
    sudo apt-get install mysql-server

    # Install phpMyAdmin.
    echo
    echo
    echo '  Installing phpMyAdmin (latest).'
    echo '  You may be asked for new passwords and options;'
    echo '    you can just press <Enter> for everything.'
    echo '  -----------------------------------------------'
    echo
    sleep 2
    sudo apt-get install phpmyadmin

    # Install SQLite (older).
    echo
    echo
    echo '  Installing SQLite (older/version 2).'
    echo '  ------------------------------------'
    echo
    sleep 2
    sudo apt-get install sqlite

    # Install SQLite 3 (latest).
    echo
    echo
    echo '  Installing SQLite 3 (latest).'
    echo '  -----------------------------'
    echo
    sleep 2
    sudo apt-get install sqlite3

    # Install PHP PDO modules.
    echo
    echo
    echo '  Installing PHP PDO modules for PostgreSQL, MySQL, and SQLite.'
    echo '  -------------------------------------------------------------'
    echo
    sleep 2
    sudo apt-get install php5-pgsql
    sudo apt-get install php5-mysql
    sudo apt-get install php5-sqlite

    # Install Ruby.
    echo
    echo
    echo '  Installing Ruby (latest).'
    echo '  -------------------------'
    echo
    sleep 2
    sudo apt-get install ruby

    # Install Python.
    echo
    echo
    echo '  Installing Python (latest).'
    echo '  ---------------------------'
    echo
    sleep 2
    sudo apt-get install python

    # Install FileZilla.
    echo
    echo
    echo '  Installing FileZilla (latest).'
    echo '  ------------------------------'
    echo
    sleep 2
    sudo apt-get install filezilla

    # Skip a line.
    echo
}

# Program-configuration functions
#================================

function ConfigureApacheMoveServerDirectory {
    echo '  Moving the default server directory to the created one.'
    echo
    sleep 0.25

    sudo mv "$DefaultServerDirectory"'*' "$ServerDirectory"'public_html/' &> /dev/null
    sudo rm -fr "$DefaultServerDirectory"
    sudo ln -s "$ServerDirectory"'public_html/' "$DefaultServerDirectoryNoSlash"
}

function ConfigureApacheCreateAceOfSpadesServer {
    # Save the name of the index page.
    IndexPage="$ServerDirectory"'public_html/index.html'

    # Check if an index already exists.
    if [ -e "$IndexPage" ]; then
        mv "$IndexPage" "$IndexPage"'.bak.aceofspades' &> /dev/null
    fi

    # Write the Ace of Spades server welcome message.
    echo '<html>' > "$IndexPage"
    echo '  <head>' >> "$IndexPage"
    echo '    <title>ace of spades</title>' >> "$IndexPage"
    echo '  </head>' >> "$IndexPage"
    echo '  <body>' >> "$IndexPage"
    echo '    <h1 style="font-size: 360%; font-weight: bold;">The ace of spades!! The ace of spades!!</h1>' >> "$IndexPage"
    echo '  </body>' >> "$IndexPage"
    echo '</html>' >> "$IndexPage"
}

# Configures the Apache program.
function ConfigureApache {
    # Declare intent.
    echo
    echo ' ==================='
    echo ' CONFIGURING Apache.'
    echo ' ==================='
    echo

    ConfigureApacheMoveServerDirectory

    ConfigureApacheCreateAceOfSpadesServer
}

# Configures the PostgreSQL program.
function ConfigurePostgreSQL {
    echo '' &> /dev/null
}

# Configures the MySQL program.
function ConfigureMySQL {
    echo '' &> /dev/null
}

# Convenience-script-creation functions
#======================================

# Creates any script files that assist in running or
# administrating Apache.
function CreateScriptsForApache {
    # Declare intent.
    echo
    echo ' ============================'
    echo ' CREATING SCRIPTS FOR Apache.'
    echo ' ============================'
    echo

    # Create scripts to start, stop, and restart Apache.
    echo '  Creating scripts to start, stop, and restart Apache.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'ApacheStart' 'Apache=`ls /etc/init.d/apache* -1 | head --lines=1`' 'sudo "$Apache" start'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'ApacheStop' 'Apache=`ls /etc/init.d/apache* -1 | head --lines=1`' 'sudo "$Apache" stop'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'ApacheRestart' 'Apache=`ls /etc/init.d/apache* -1 | head --lines=1`' 'sudo "$Apache" restart'

    # Skip a line.
    echo
}

# Creates any script files that assist in running or
# administrating PostgreSQL.
function CreateScriptsForPostgreSQL {
    # Declare intent.
    echo
    echo ' ================================'
    echo ' CREATING SCRIPTS FOR PostgreSQL.'
    echo ' ================================'
    echo

    # Create scripts for execution as the postgres user.
    echo '  Creating scripts to execute the PostgreSQL admin user (postgres).'
    sleep 0.25
    CreateScriptAndLowercaseAlias "$ScriptsDirectory"'PostgreSQLExecuteScriptAsPostgres' 'sudo -u postgres -s "$@"'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLExecuteAsPostgres' 'sudo -u postgres "$@"'

    # Create scripts to add PostgreSQL users and databases.
    echo '  Creating scripts to add PostgreSQL users and databases.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLCreateSuperUser' 'PostgreSQLExecuteAsPostgres createuser -s "$1" -P -e'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLCreateUser' 'PostgreSQLExecuteAsPostgres createuser "$1" -P -e'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLCreateDatabase' 'PostgreSQLExecuteAsPostgres createdb "$1"'

    # Create scripts to start, stop, and restart PostgreSQL.
    echo '  Creating scripts to start, stop, and restart PostgreSQL.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLStart' 'PostgreSQL=`ls /etc/init.d/postgres* -1 | head --lines=1`' 'sudo "$PostgreSQL" start'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLStop' 'PostgreSQL=`ls /etc/init.d/postgres* -1 | head --lines=1`' 'sudo "$PostgreSQL" stop'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLRestart' 'PostgreSQL=`ls /etc/init.d/postgres* -1 | head --lines=1`' 'sudo "$PostgreSQL" restart'

    # Create scripts to use and administrate PostgreSQL.
    echo '  Creating scripts to use and administrate PostgreSQL.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQLAdmin' 'pgadmin3'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'PostgreSQL' '# Connect to a database ($1) with a username ($2), possibly including other options ($>2)' 'Database=$1' 'Username=$2' 'shift 2' 'psql -d "$Database" "$Username" -W "$@"'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'phpPgAdmin' 'firefox http://localhost/phppgadmin &'

    # Skip a line.
    echo
}

# Creates any script files that assist in running or
# administrating MySQL.
function CreateScriptsForMySQL {
    # Declare intent.
    echo
    echo ' ==========================='
    echo ' CREATING SCRIPTS FOR MySQL.'
    echo ' ==========================='
    echo

    # Create a script for initializing the root password.
    echo '  Creating a script to initialize the root password.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLInitializeRootPassword' '# Accepts a first password ($1) for the root user.' 'mysqladmin -u root password "$1"'

    # Create a script for changing a user's password.
    echo '  Creating a script to change a user'"'"'s password.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLChangePassword' '# Accepts a new password ($3) for a given user ($1), requiring the old password ($2).' 'mysqladmin -u "$1" -p"$2" password "$3"'

    # Create scripts to start, stop, and restart MySQL.
    echo '  Creating scripts to start, stop, and restart MySQL.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLStart' 'MySQL=`ls /etc/init.d/mysql* -1 | head --lines=1`' 'sudo "$MySQL" start'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLStop' 'MySQL=`ls /etc/init.d/mysql* -1 | head --lines=1`' 'sudo "$MySQL" stop'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLRestart' 'MySQL=`ls /etc/init.d/mysql* -1 | head --lines=1`' 'sudo "$MySQL" restart'

    # Create scripts to use and administrate MySQL.
    echo '  Creating scripts to use and administrate MySQL.'
    sleep 0.25
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQLAdmin' 'mysqladmin'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'MySQL' '# Connect to a database ($1) with a username ($2) and a password ($3), possibly including other options ($>3)' 'Database=$1' 'Username=$2' 'Password=$3' 'shift 3' 'mysql --user="$Username" -p"$Password" "$Database" "$@"'

    # Skip a line.
    echo
}

# Creates any script files that assist in running or
# administrating SQLite.
function CreateScriptsForSQLite {
    # Declare intent.
    echo
    echo ' ============================'
    echo ' CREATING SCRIPTS FOR SQLite.'
    echo ' ============================'
    echo

    # Create scripts to use SQLite.
    echo '  Creating scripts to use SQLite.'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'SQLite' 'sqlite "$@"'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'SQLite2' 'sqlite "$@"'
    CreateScriptAndLowercaseAlias  "$ScriptsDirectory"'SQLite3' 'sqlite3 "$@"'

    # Skip a line.
    echo
}

# Startup-management functions
#=============================

# Creates any script files that assist in starting Apache
# when the OS starts.
function CreateStartupScriptsForApache {
    echo '' &> /dev/null
}

# Creates any script files that assist in starting PostgreSQL
# when the OS starts.
function CreateStartupScriptsForPostgreSQL {
    echo '' &> /dev/null
}

# Creates any script files that assist in starting MySQL
# when the OS starts.
function CreateStartupScriptsForMySQL {
    echo '' &> /dev/null
}

# INTRODUCTION
##############

echo
echo 'Website Architecture Server Setup'
echo '---------------------------------'
echo

# ENVIRONMENT & FILESYSTEM PREPARATION
######################################

ModifyEnvironmentAndFilesystem

# INSTALLATION & CONFIGURATION PROCESS
######################################

InstallPackages

ConfigureApache
ConfigurePostgreSQL
ConfigureMySQL

CreateScriptsForApache
CreateScriptsForPostgreSQL
CreateScriptsForMySQL
CreateScriptsForSQLite

CreateStartupScriptsForApache
CreateStartupScriptsForPostgreSQL
CreateStartupScriptsForMySQL

# FINISH
########

echo 'DONE. You should restart the computer.'
echo

