#!/bin/sh
#RELEASE_DATETIME=`ls -l /www/opals | sed -e 's/^.*> opals-//'`

############################################################
# Only root can add a site
############################################################
if [ $EUID -ne 0 ]
then
    echo Aborted: Only root can add a site.
    exit -1
fi
############################################################

# Source global settings
if [ -f /etc/opals/opalsrc ]
then
    . /etc/opals/opalsrc
else
    echo ERROR: /etc/opals/opalsrc not found.
    exit -2
fi


################################################################################
# Random password generator
################################################################################
# Random password generator for bash 2.x by Antek Sawicki <tenox@tenox.tc>,
# who generously gave permission to the document author to use it here.
#
# ==> Comments added by document author ==>
function genPass () {
    MATRIX="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz%^_+=-,."
    LENGTH="12"
    # ==> May change 'LENGTH' for longer password, of course.

    while [ "${n:=1}" -le "$LENGTH" ]
    # ==> Recall that := is "default substitution" operator.
    # ==> So, if 'n' has not been initialized, set it to 1.
    do
        PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
        # ==> Very clever, but tricky.

        # ==> Starting from the innermost nesting...
        # ==> ${#MATRIX} returns length of array MATRIX.

        # ==> $RANDOM%${#MATRIX} returns random number between 1
        # ==> and length of MATRIX - 1.

        # ==> ${MATRIX:$(($RANDOM%${#MATRIX})):1}
        # ==> returns expansion of MATRIX at random position, by length 1. 
        # ==> See {var:pos:len} parameter substitution in Section 3.3.1
        # ==> and following examples.

        # ==> PASS=... simply pastes this result onto previous PASS (concatenation).

        # ==> To visualize this more clearly, uncomment the following line
        # ==>             echo "$PASS"
        # ==> to see PASS being built up,
        # ==> one character at a time, each iteration of the loop.

        let n+=1
        # ==> Increment 'n' for next pass.
    done

    echo "$PASS"      # ==> Or, redirect to file, as desired.
}
################################################################################
################################################################################
JVM_VERSION='1.6'
RPM_LIST=""
RPM_LIST="$RPM_LIST httpd"
RPM_LIST="$RPM_LIST idzebra-2.0"
RPM_LIST="$RPM_LIST yaz"
RPM_LIST="$RPM_LIST libyaz3"
#RPM_LIST="$RPM_LIST mysql"
#RPM_LIST="$RPM_LIST mysql-server"
RPM_LIST="$RPM_LIST perl"
RPM_LIST="$RPM_LIST curl"

PERL_LIST="$PERL_LIST DBI"
PERL_LIST="$PERL_LIST Bit::Vector"
PERL_LIST="$PERL_LIST Date::Calc"
PERL_LIST="$PERL_LIST Digest::SHA"
PERL_LIST="$PERL_LIST HTML::Template"
PERL_LIST="$PERL_LIST MARC::Charset"
PERL_LIST="$PERL_LIST MARC::Record"
PERL_LIST="$PERL_LIST MARC::File::XML"
PERL_LIST="$PERL_LIST MIME::Lite"
PERL_LIST="$PERL_LIST ZOOM"
PERL_LIST="$PERL_LIST PDF::API2"
PERL_LIST="$PERL_LIST PDF::Create"
PERL_LIST="$PERL_LIST Text::Aspell"
PERL_LIST="$PERL_LIST Text::CSV_XS"
PERL_LIST="$PERL_LIST Time::HiRes"
PERL_LIST="$PERL_LIST Email::Date"
PERL_LIST="$PERL_LIST Email::Date::Format"

ERROR_REQUIREMENT_FAILED=1
ERROR_USAGE=2
ERROR_EMPTY_LINK=3
ERROR_INVALID_LINK=4
ERROR_VERSION_MISMATCHED=5
ERROR_INVALID_SQL_ROOT_PASSWD=6
ERROR_NON_UNIQUE_SITECODE=7
ERROR_EXISTING_SITE_URL=8
ERROR_SETUP_ABORTED=9
ERROR_INVALID_SITETYPE=10
ERROR_JVM_NOT_EXECUTABLE=11
ERROR_JVM_VERSION_MISMATCHED=12
#ERROR_JVM_PATH_NOT_SPECIFIED=13

OPL_TMP=/tmp

#zRoot='/data/idzebra'
#zPort='210'
#imex='/data/opals'
#opals_www='/www'
#opals_etc='/etc/opals'
#OPALSRC="$opals_etc/opalsrc"
#jBin=/opt/java/jdk/bin/java
#opals_httpd_dir='/etc/httpd/conf.d/opals'

abort_msg='Installation aborted.'
script=`basename $0`

#sql_client_host=`hostname`
#sql_client_host=`host $sql_client_host | awk '/has address/ {print $1}'`
dbName=
dbUser=
dbPass=
#sql_server_host=
#sql_addsite_user=
#sql_addsite_pass=
zdbName=
sysCode=
sysName=
sysNameQuoted=
libCode=
libName=
libraryType=
libNameQuoted=
siteCode=
siteType=
siteUrl=
webmasterEmail=
#opals_link=opals
holiday_on=
############################################################

function showUsage() {
    cat << _USAGE_
Usage:   $script -l OPALS_LINK [-j JVM_ABSOLUTE_PATH]
Example: $script
         $script -l opals
         $script -l opals -j /opt/java/jre/bin/java
_USAGE_
}

############################################################
###################### Parse options #######################
############################################################
while getopts "j:l:" option; do
    case $option in
        j) jBin=$OPTARG
           ;;
        l) opals_link=$OPTARG
           ;;
        *) showUsage
           exit $ERROR_USAGE
           ;;
    esac
done
############################################################
######################/Parse options #######################
############################################################

############################################################

function checkRequirement() {
    echo -n "Check OPALS's requirements... "

    req_ok=1
    for i in $RPM_LIST; do
        rpm -q $i > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "failed: $i not found."
            req_ok=0
        fi
    done

    for i in $PERL_LIST; do
        perl -e "use $i" > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "failed: Perl module $i not found."
            req_ok=0
        fi
    done

    if [ $req_ok -eq 0 ]; then
        exit $ERROR_REQUIREMENT_FAILED
    fi

    echo OK.
}
############################################################

function checkVersion() {
    echo -n 'Check OPALS version... '
    if [ "$opals_link" == "" ]; then
        echo 'empty link.'
        showUsage
        exit $ERROR_EMPTY_LINK
    fi

    if [ ! -d $opals_www/$opals_link ]; then
        echo "invalid link $opals_www/$opals_link"
        exit $ERROR_INVALID_LINK
    fi

#    addScript=$opals_www/$opals_link/install/addsite
#    release_datetime=`grep ^RELEASE_DATETIME $addScript | cut -d'=' -f2`
#    if [ "$release_datetime" != "$RELEASE_DATETIME" ]; then
#        echo 'not matched.'
#        exit $ERROR_VERSION_MISMATCHED
#    fi

    echo 'OK.'
}
############################################################

function checkJvm() {
    echo -n "Check JVM version $JVM_VERSION... "

    if [ "$jBin" == "" ]; then
        echo "JVM path not specified"
        showUsage
        exit $ERROR_JVM_PATH_NOT_SPECIFIED
    fi

    # Check if JVM exists and executable
    if [ ! -f $jBin/java ] || [ ! -x $jBin/java ]; then
        echo "cannot execute JVM $JVM_VERSION: $jBin/java"
        showUsage
        exit $ERROR_JVM_NOT_EXECUTABLE
    fi

    # Check JVM version
    #jVersion=`$jBin -version 2>&1 | head -n1 | grep "version \"$JVM_VERSION"`
    jVersion=`$jBin/java -version 2>&1 | grep "version \"$JVM_VERSION"`
    if [ $? -ne 0 ]; then
        echo "required JVM $JVM_VERSION mismatched: $jVersion ($jBin/java)"
        exit $ERROR_JVM_VERSION_MISMATCHED
    fi

    jBin=`dirname $jBin`

    echo 'OK.'
}
############################################################

function checkSqlAdminLogin() {
    testFile=$opals_www/$opals_link/install/sql/test.sql

    echo -n 'Check SQL login... '
    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass < $testFile
    if [ $? -ne 0 ]
    then
        echo $abort_msg
        exit $ERROR_INVALID_SQL_ROOT_PASSWD
    fi

    echo OK.
}
############################################################

function normalize_syslibCode() {
    echo $1 | tr -d '[:space:][:punct:]' | tr '[:upper:]' '[:lower:]'
}
############################################################

function readSite_code_name() {
    echo -n 'Enter system code: '
    read sysCode
    echo -n 'Enter system name: '
    read sysName
    echo -n 'Enter library code: '
    read libCode
    echo -n 'Enter library name: '
    read libName

    sysCode=`normalize_syslibCode $sysCode`
    libCode=`normalize_syslibCode $libCode`

    siteCode="$sysCode"_"$libCode"

    if [ -d $zRoot/$zPort/record/$siteCode ]; then
        echo -n 'Site exists. Retry? (y/n) '
        read answer
        if [ "$answer" == 'y' ]; then
            readSite_code_name
            return $?
        else
            echo $abort_msg
            exit $ERROR_NON_UNIQUE_SITECODE
        fi
    fi

    sysNameQuoted=`echo $sysName | perl -pi -e "s/'/\\\\\\'/g"`
    libNameQuoted=`echo $libName | perl -pi -e "s/'/\\\\\\'/g"`

    return 0
}
############################################################

function setDbParam() {
    dbName=$siteCode
    dbUser=$siteCode
    dbPass=`genPass`
    zdbName=$siteCode
}
############################################################

function readSiteType() {
    echo -n 'Enter site type (0: branch, 1: union, 2:ILL): '
    read siteType
    siteType=`echo $siteType|tr -d '[:alpha:][:space:][:punct:][:blank:][:cntrl:]'`
    if [ "$siteType" == "" ]; then
        echo -n 'Invalid stie type. Retry? (y/n) '
        read answer
        if [ "$answer" == 'y' ]; then
            readSiteType
            return $?
        else
            echo $abort_msg
            exit $ERROR_INVALID_SITETYPE
        fi
    fi

    if [ $siteType -lt 0 ] || [ $siteType -gt 2 ]; then
        siteType=0
    fi

    return 0
}
############################################################

function readSiteUrl() {
    echo -n 'Enter site URL (eg. www.example.com): '
    read siteUrl

    #urlExisting=`grep -i "ServerName $siteUrl\b" /etc/httpd/conf/httpd.conf`
    #if [ "$urlExisting" != "" ]; then
    if [ -f "$opals_httpd_dir/$siteUrl.conf" ]; then
        echo -n 'URL exists. Retry? (y/n) '
        read answer
        if [ "$answer" == 'y' ]; then
            readSiteUrl
            return $?
        else
            echo $abort_msg
            exit $ERROR_EXISTING_SITE_URL
        fi
    fi

    return 0
}
############################################################

function readSiteEmail() {
    echo -n "Webmaster email: "
    read webmasterEmail
}
############################################################

function readHolidaysSettings() {
    echo -n "Do you want to show holidays in beginner search? (y/n) "
    read holiday_on
    holiday_on=`echo $holiday_on | tr [:upper:] [:lower:]`

    if [ "$holiday_on" != "y" ] && [ "$holiday_on" != "n" ]; then
        echo "Please answer 'y' or 'n'."
        readHolidaysSettings
        return $?
    fi

    return 0
}
############################################################

function confirmInfo() {
    cat << _CONFIRM_
Please confirm that the following settings are correct:
Hostname:             $sql_client_host
OPALS link:           $opals_link
JVM path:             $jBin
System code:          $sysCode
System name:          $sysName
Library code:         $libCode
Library name:         $libName
Site type:            $siteType
Site URL:             $siteUrl
Webmaster's email:    $webmasterEmail
SQL database server:  $sql_server_host
SQL database name:    $dbName
SQL database user:    $dbUser
Zebra database name:  $zdbName
Solr database name:   $zdbName
Show holidays in beginner search: $holiday_on

_CONFIRM_
    echo -n 'Continue adding site? (y/n) '

    read answer
    echo
    while [ "$answer" != 'y' ] && [ "$answer" != 'n' ]; do
        echo -n "Please answer 'y' or 'n'. Continue adding site? (y/n) "
        read answer
    done

    if [ "$answer" == 'n' ]; then
        echo $abort_msg
        exit $ERROR_SETUP_ABORTED
    fi

    if [ "$sql_server_host" == "localhost" ]; then
        sql_client_host='localhost'
    fi
}
############################################################

function writeConfig() {
    siteConfig=$opals_etc/conf/$siteCode
    (cat << EOF
# SQL database settings:
db_driver=mysql
db_name=$dbName
db_host=$sql_server_host
db_port=3306
db_user=$dbUser
db_password=$dbPass
 
# Zebra database settings:
zebraidx=/usr/bin/zebraidx
zRoot=$zRoot
zHost=localhost
zPort=$zPort
zDatabase=$zdbName
zindex=on
 
# Template location???
rootDir=$opals_www/$opals_link
type=$siteType

jBin=$jBin
imex=$opals_tmp
showHolidays=$holiday_on

#solr info
sHost=localhost
sPort=8983

EOF
) > $siteConfig

    group=opals
    if [[ "$(getent group $group)" == "" ]]
    then
        group=root
    fi

    chmod 460 $siteConfig
    #chgrp apache $siteConfig
    chown apache.$group $siteConfig
}
############################################################

function addVirtualhost() {
    dateTime=`date +%Y%m%d-%H%M%S`
    conf_file="$opals_httpd_dir/$siteUrl.conf"
    if [ -f $conf_file ]; then
        echo "WARNING: $conf_file exists. Your configuration is saved in $conf_file.$dateTime instead."
        conf_file="$conf_file.$dateTime"
    fi

    httpd_2_4_req="
  <Directory $opals_www/$opals_link/bin>
    AllowOverride None
    Require all granted
  </Directory>
  <Directory $opals_www/$opals_link/htdocs>
    AllowOverride None
    Require all granted
  </Directory>
"

    if [[ $(rpm -q --qf '%{version}' httpd|cut -d. -f2) -lt 4 ]]; then
      httpd_2_4_req=
    fi

    (cat << _CONF_
############################################################
# Site ($siteCode) added at $dateTime.
<VirtualHost *:80>
  ServerAdmin $webmasterEmail
  ServerName  $siteUrl
  ErrorLog    logs/$siteCode-e
  TransferLog logs/$siteCode-a
  DocumentRoot $opals_www/$opals_link/htdocs
$httpd_2_4_req
  ScriptAlias /bin  $opals_www/$opals_link/bin
  SetEnv PERL5LIB   $opals_www/$opals_link/module
  SetEnv OPALS_ROOT $opals_www/$opals_link
  SetEnv OPALS_CONF $opals_etc/conf/$siteCode

  RewriteEngine on
  RewriteRule /ebook/reader/([^/]+)   /bin/ebook/reader?bid=\$1 [PT] 
  RewriteRule /ebook/([^/]+)/([^/]+)  /bin/ebook/file?bid=\$1&fid=\$2 [PT]
  RewriteRule /doc/([^/]+)            /bin/util/getFile?fileId=$1 [PT]
</VirtualHost>
_CONF_
) > $conf_file
}
############################################################

function createSqlDatabase() {
    # SQL file to create user
    userSqlFile=$OPL_TMP/$siteCode.user.sql
    (cat << _SQL_
grant select, insert, update, delete, create, drop, alter, index, lock tables on $dbName.* to $dbUser@$sql_client_host identified by '$dbPass';
create database if not exists $dbName;
flush privileges;
_SQL_
) > $userSqlFile

    # SQL file to create database and tables
    month=`date +%m`
    yearFirst=`date +%Y`
    yearLast=$yearFirst
    if [ "$month" -lt '07' ]; then
        yearFirst=$[ --yearFirst ]
    else
        yearLast=$[ ++yearLast ]
    fi
    tables_data=$OPL_TMP/$siteCode.sql
    cat $opals_www/$opals_link/install/sql/opals-db.sql          >  $tables_data
    cat $opals_www/$opals_link/install/sql/opals-defaultData.sql >> $tables_data
    (cat << _SQL_
insert into opl_preference values 
    ('libcode','$libCode','$libCode','string','text','Library code',0,1,7),
    ('libname','$libNameQuoted','$libNameQuoted','string','text','Library name',0,1,8),
    ('dateFirst','$yearFirst-09-01','$yearFirst-09-01','','text','',1,NULL,NULL),
    ('dateLast','$yearLast-06-30','$yearLast-06-30','','text','',1,NULL,NULL),
    ('libraryType','$libraryType','$libraryType',null,'radio','Library type; K-12, college or public',0,1,7);

delete from opl_libSystem;
delete from opl_library;
insert into opl_libSystem (sCode, sName) values
    ('-N\/A-', 'Not Applicable'),
    ('', 'New System');
insert into opl_library (sysCode, lCode, lName) values
    ('-N\/A-', '-N\/A-', 'Not Applicable'),
    ('', '', 'New Library');
_SQL_
) >> $tables_data

    if [ $siteType -eq 0 ]; then
        (cat << _SQL_
insert into opl_libSystem set sCode=upper('$sysCode'),sName='$sysNameQuoted';
insert into opl_library set sysCode=upper('$sysCode'),lCode=upper('$libCode'),lName='$libNameQuoted';
_SQL_
) >> $tables_data
    fi

    #  SQL file to import data
    opl_file=$opals_www/$opals_link/install/sql/opl_file.sql
    opl_menuItem=$opals_www/$opals_link/install/sql/opl_menuItem.sql
    template=$OPL_TMP/$siteCode.template.sql
    opl_deweyDesc=$opals_www/$opals_link/install/sql/opl_deweyDesc.sql
    cat $opals_www/$opals_link/install/sql/opl_template.sql > $template

    uppercaseCode=`echo $sysCode | tr [:lower:] [:upper:]`
    perl -pi -e "s|__852_a__|$uppercaseCode|g" $template

    uppercaseCode=`echo $libCode | tr [:lower:] [:upper:]`
    perl -pi -e "s|__852_b__|$uppercaseCode|g" $template

    # Execute SQL file
    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass mysql < $userSqlFile
#    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass $dbName < $tables_data
#    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass $dbName < $opl_file
#    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass $dbName < $opl_menuItem
#    mysql -h$sql_server_host -u$sql_addsite_user -p$sql_addsite_pass $dbName < $template
    mysql -h$sql_server_host -u$dbUser -p$dbPass $dbName < $tables_data
    mysql -h$sql_server_host -u$dbUser -p$dbPass $dbName < $opl_file
    mysql -h$sql_server_host -u$dbUser -p$dbPass $dbName < $opl_menuItem
    mysql -h$sql_server_host -u$dbUser -p$dbPass $dbName < $template
    mysql -h$sql_server_host -u$dbUser -p$dbPass $dbName < $opl_deweyDesc
}
############################################################

function createZebraDatabase() {
    waiting_time=10
    #/opt/opals/bin/zdb_create -cd $zdbName
    opl-zdb-create -cd $zdbName
    while [ "$?" -eq 255 ]
    do
        echo Waiting for $waiting_time seconds...
        sleep $waiting_time
        #/opt/opals/bin/zdb_create -cd $zdbName
        opl-zdb-create  -cd $zdbName
    done

#    mkdir -p $zRoot/$zPort/record/$siteCode/1
#    GROUP=apache
#    grep opals /etc/group > /dev/null 2>&1
#    if [ $? -eq 0 ]; then
#        GROUP=opals
#    fi
#    chown apache.$GROUP $zRoot/$zPort/record/$siteCode/1
#    chmod u+rwx,g+rwxs,o+rx $zRoot/$zPort/record/$siteCode/1
#    cp -p $opals_www/$opals_link/install/sample/dummy.xml $zRoot/$zPort/record/$siteCode/1/
#    /opt/opals/bin/zindex_update $siteCode 1
#
#    \rm -f $zRoot/$zPort/record/$siteCode/1/dummy.xml
#    /opt/opals/bin/zindex_update $siteCode 1
}
############################################################

function createImExDir() {
    mkdir -p $opals_tmp/{im,ex}port/$siteCode
    chown apache.apache $opals_tmp/{im,ex}port
    chown apache.apache $opals_tmp/{im,ex}port/$siteCode
}
############################################################

function reloadWebServer() {
  reloaded=0

  if [[ -x /etc/rc.d/init.d/httpd ]]; then
    service=/sbin/service
    $service httpd configtest > /dev/null 2>&1
    if [ $? -eq 0 ]; then
      $service httpd reload
      reloaded=1
    fi
  else
    apachectl configtest > /dev/null 2>&1
    if [ $? -eq 0 ]; then
      systemctl reload httpd
      reloaded=1
    fi
  fi

  if [[ $reloaded -eq 1 ]]; then
    cat << _MSG_
New site <http://$siteUrl> is ready.
_MSG_
  fi
}
################################################################################
function addSolrDB(){
  if [[ -f /etc/default/jetty ]]
  then
    instanceDir=`grep solr.home /etc/default/jetty|cut -d= -f3|cut -d ' ' -f1`
  else
    for i in jetty opl-solr-jetty opl-solr; do
      [[ -f /etc/sysconfig/${i} ]] && . /etc/sysconfig/${i}
    done
    instanceDir=$SOLR_INSTANCE_DIR
  fi

  echo "adding Solr index DB $siteCode"
  curl "http://localhost:8983/solr/admin/cores?action=CREATE&instanceDir=$instanceDir&dataDir=/data/solr/$siteCode&name=$siteCode"
}
################################################################################
#checkRequirement
#checkVersion
#checkJvm
checkSqlAdminLogin

readSite_code_name
setDbParam
readSiteType
if [ $siteType == 0 ]
    then
        echo -n 'Enter library type(0: K-12, 1: academic, 2:public library):  '
        read typeCode
        if [ "$typeCode" == "2" ];then
            libraryType='public'
        elif  [ "$typeCode" == "1" ]; then
            libraryType='academy'
        else
            libraryType='k-12'
        fi
fi    
readSiteUrl
readSiteEmail
readHolidaysSettings

confirmInfo

#writeConfig: imDir -> imex in config file: update files using imDir
writeConfig
addVirtualhost
createSqlDatabase
createZebraDatabase
createImExDir

#create solr index db
addSolrDB

reloadWebServer

exit 0
