/********************************************************************
          FILE:          cyindex.cpp
   DESCRIPTION:          index class implementation
 ********************************************************************/
//////////////////////////////////////////
//  Main header file
#include "cyindex.h"
//////////////////////////////////////////
//  CYWare header file(s)
#include "cyw_js.h"
#include "json/json.h"
#include "col/column_array.h"
using namespace std;
/*******************************************************************
      FUNCTION:          cyindex
   DESCRIPTION:          Constructor
 *******************************************************************/
cyindex::cyindex (cyjs* js,
                  string inisection,
                  string cginame)
{
    _js = js;
    _cginame = cginame;
    _inisection = inisection;

    _appcode  = "pjgabcarcis";
    _appname  = _js->_ini->get_value("SHOPIFY","APPNAME");
    _shopname = "all-saints-demo.myshopify.com";
}
/*******************************************************************
      FUNCTION:          cyindex
   DESCRIPTION:          Destructor
 *******************************************************************/
cyindex::~cyindex ()
{
}
/*******************************************************************
      FUNCTION:          page_main
   DESCRIPTION:          The main page
     ARGUMENTS:          NONE
       RETURNS:          HTML
 *******************************************************************/
string                   cyindex::page_default ()
{
    //////////////////////////////////////
    //  Retrieve argument(s)
    string error = _js->_cgi->form ("errormsg");
    string username = _js->_cgi->form ("username");
    //////////////////////////////////////
    //  Login page
    stringstream out;
    out << _js->_html->header (_js->_ini->get_value ("GENERAL","TITLE"))
        << "</head>" << endl
        << "<body>" << endl
        << "<div id=\"container\" class=\"container\">" << endl
        << "  <div class=\"row\">" << endl
        << "    <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "      <div class=\"col-xs-10 col-sm-6\">" << endl
        << "        <img src=\"/storm/images/logosm.png\" class=\"img-responsive center-block d-block mx-auto\" alt=\"Logo\">" << endl
        << "        <h4 class=\"text-center\">" << endl
        << "          " << _js->_ini->get_value("GENERAL","TITLE") << endl
        << "        </h4>" << endl
        << "        <div class=\"text-center\">" << endl
        << "          Version" << _js->_ini->get_value("GENERAL","VERSION") << endl
        << "        </div>" << endl;
    //////////////////////////////////////
    //  Error message
    if (error.size () > 0)  {
        if (error == "true")  {
            out << "        <h4 class=\"text-success text-center\">" << endl
                << "          Password successfuly changed.<br>Please sign in using new password." << endl
                << "        </h4>" << endl;
        } else {
            out << "        <h4 class=\"text-danger text-center\">" << endl
                << "          " << error << endl
                << "        </h4>" << endl;
        }
    }
    out << "      </div>" << endl
        << "      <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "    </div>" << endl
        << "    <div class=\"row\">" << endl
        << "      <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "      <div class=\"col-xs-10 col-sm-6\">" << endl;
    //////////////////////////////////////
    //  Login form
    out << _js->_html->form(6,"frmlogin","credentials","post","","",true,_cginame)
        << _js->_html->input_lbl (8,js_nocase,32,true,false,"username",username,"text",
                                  "Username","","^[a-zA-Z0-9-]+$","")
        << _js->_html->input_lbl (8,js_nocase,64,true,false,"password","","password",
                                  "Password","","^[a-zA-Z0-9-_=*^$#@!]+$","")
        << "      </form>" << endl
        << "      <input type=\"checkbox\" onclick=\"show_pass()\"> Show Password" << endl
        << "      <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "      <button type=\"submit\" form=\"frmlogin\" class=\"btn btn-primary btn-block\">" << endl
        << "        <span class=\"fa fa-ok\"></span>Sign In" << endl
        << "      </button>" << endl
        << "    </div>" << endl
        << "    <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "  </div>" << endl
        << "</div>" << endl
        << "<script type=\"text/javascript\">" << endl
        << "  $( document ).ready(function() {" << endl
        << "    $(function()  {" << endl
        << "      $('#username').focus ();" << endl
        << "    });" << endl
        << "  });" << endl
        << "  function show_pass() {" << endl
        << "    var password = document.getElementById('password');" << endl
        << "    if (password.type === 'password') {" << endl
        << "        password.type = 'text';" << endl
        << "    } else {" << endl
        << "        password.type = 'password';" << endl
        << "      }" << endl
        << "    }   " << endl
        << "</script>" << endl
        << "</body>" << endl
        << "</html>" << endl;
    return (out.str ());
}
/*******************************************************************
      FUNCTION:          page_about
   DESCRIPTION:          About web page
     ARGUMENTS:          NONE
       RETURNS:          HTML
 *******************************************************************/
string                   cyindex::page_about ()
{
    //////////////////////////////////////
    //  About page
    stringstream out;
    out << _js->_html->header (_js->_ini->get_value ("GENERAL","TITLE"))
        << "</head>" << endl
        << "<body>" << endl
        << "<div id=\"container\" class=\"container\">" << endl
        << "  <div class=\"row\">" << endl
        << "    <div class=\"col-xs-1 col-sm-3\">&nbsp;</div>" << endl
        << "      <div class=\"col-xs-10 col-sm-6\">" << endl
        << "        <img src=\"/storm/images/logosm.png\" class=\"img-responsive center-block d-block mx-auto\" alt=\"Logo\">" << endl
        << "        <h4 class=\"text-center\">" << endl
        << "          " << _js->_ini->get_value("GENERAL","TITLE") << endl
        << "        </h4>" << endl
        << "        <div class=\"text-center\">" << endl
        << "          Version" << _js->_ini->get_value("GENERAL","VERSION") << endl
        << "        </div>" << endl
        << "      </div>" << endl
        << "    </div>" << endl
        << "  </div>" << endl
        << "</div>" << endl
        << "</body>" << endl
        << "</html>" << endl;
    return (out.str ());
}
/*******************************************************************
      FUNCTION:          page_treemenu
   DESCRIPTION:          The main menu tree JSON
     ARGUMENTS:          NONE
       RETURNS:          JSON tree hierarchy
 *******************************************************************/
string                   cyindex::page_treemenu ()
{
    string               result,
                         group_code = _js->_cgi->form ("group_code");
    ///////////////////////////////////////
    //  Validate the group code
    if (!_js->_util->valid_alpha("group_code",group_code.c_str (), 1, 10))
        return _js->_util->json_error(_js->_util->errormsg());
    ///////////////////////////////////////
    //  Database connection(s)
    //cywaredb cydb (_js->_ini);
    CYDbSql* db1 = _js->_cydb->dbconn (_inisection);
    CYDbSql* db2 = _js->_cydb->dbconn (_inisection);
    CYDbSql* db3 = _js->_cydb->dbconn (_inisection);
    CYDbSql* dbcheck = _js->_cydb->dbconn (_inisection);
    if (NULL == db1 || NULL == db2 ||
        NULL == db3 || NULL == dbcheck)  {
        _js->_log->logmsg("cyw_tree::mainmenu", _js->_cydb->errormsg ().c_str ());
        return _js->_util->json_error ("Unable to connect to the database");
    }
    ///////////////////////////////////////
    //  Retrieve all module(s)
    stringstream sql;
    sql.clear ();
    sql.str(string(""));
    sql << "select   a.module_id, a.module_name "
        << "from     tg_gui_module a "
        << "where    a.module_id in (select distinct(z.module_id) from tg_group_module z "
        << "                      where  z.group_code = '" << group_code << "' "
        << "                      and    z.is_active = 1) "
        << "order by a.module_id asc ";
    db1->sql_reset ();
    if (!db1->sql_result (sql.str ().c_str ()))   {
        _js->_log->logmsg("cyw_tree::mainmenu", db1->errordb ().c_str ());
        return _js->_util->json_error ("Unable to retrieve the menu module");
    }
    ///////////////////////////////////////
    //  Tree root
    Json::Value          jroot;
    if (db1->eof ())   {
        _js->_log->logmsg("cyw_tree::mainmenu", db1->errordb ().c_str ());
        return _js->_util->json_error ("No valid modules found");
    }  else  {
        ///////////////////////////////////
        //  Go through every module
        int              nmodule;
        Json::Value      jmodule;

        nmodule = 0;
        while (!db1->eof ())  {
            ///////////////////////////////
            //  module values
            string module_id = db1->sql_field_value ("module_id");
            string module_name = db1->sql_field_value ("module_name");
            ///////////////////////////////
            //  module array
            string id = module_id;
            jmodule [nmodule]["id"] = id;
            jmodule [nmodule]["type"] = "module";
            jmodule [nmodule]["text"] = module_name;
            ///////////////////////////////
            //  Retrieve category
            sql.clear ();
            sql.str(string(""));
            sql << "select   a.category_id, a.category_name "
                << "from     tg_gui_category a "
                << "where    a.module_id = " << module_id << " "
                << "and      a.category_id in "
                << "         (select distinct(z.category_id) from tg_gui_menu z "
                << "          where  z.module_id = " << module_id << " "
                << "          and    z.menu_id in (select x.menu_id from tg_group_module x "
                << "                               where  x.group_code = '" << group_code << "' "
                << "                               and    x.module_id = " << module_id << " "
                << "                               and    x.is_active = 1)) "
                << "order by a.category_id ";
            db2->sql_reset ();
            if (!db2->sql_result (sql.str ().c_str ()))   {
                _js->_log->logmsg("cyw_tree::mainmenu", db2->errordb ().c_str ());
                return _js->_util->json_error ("Unable to retrieve the menu category");
            }
            ///////////////////////////////
            //  category
            int          ncategory;
            Json::Value  jcategory;

            ncategory = 0;
            jcategory.clear ();
            while (!db2->eof ())  {
                ///////////////////////////////
                //  category values
                string category_id = db2->sql_field_value ("category_id");
                string category_name = db2->sql_field_value ("category_name");
                ///////////////////////////////
                //  category array
                id  = module_id;
                id += "-";
                id += category_id;
                jcategory [ncategory]["id"] = id;
                jcategory [ncategory]["type"] = "category";
                jcategory [ncategory]["text"] = category_name;
                ///////////////////////////////
                //  Retrieve menu items
                sql.clear ();
                sql.str(string(""));
                sql << "select   a.* "
                    << "from     tg_gui_menu a "
                    << "where    a.module_id = " << module_id << " "
                    << "and      a.category_id = " << category_id << " "
                    << "and      a.menu_id in (select x.menu_id from tg_group_module x "
                    << "                       where  x.group_code = '" << group_code << "' "
                    << "                       and    x.module_id = " << module_id << " "
                    << "                       and    x.is_active = 1) "
                    << "order by a.menu_id asc ";
                db3->sql_reset ();
                if (!db3->sql_result (sql.str ().c_str ()))   {
                    _js->_log->logmsg("cyw_tree::mainmenu", db3->errordb ().c_str ());
                    return _js->_util->json_error ("Unable to retrieve the menu item");
                }
                ///////////////////////////////
                //  menu
                int          nmenu;
                string       url;
                Json::Value  jmenu;

                nmenu = 0;
                jmenu.clear ();
                while (!db3->eof ())  {
                    ///////////////////////////////
                    //  Menu field(s)
                    string menu_id = db3->sql_field_value ("menu_id");
                    string menu_name = db3->sql_field_value ("menu_name");
                    string menu_page = db3->sql_field_value ("menu_page");
                    string menu_script = db3->sql_field_value ("is_script").c_str ();
                    string menu_schema = db3->sql_field_value ("menu_schema_name").c_str ();
                    string menu_library = db3->sql_field_value ("menu_library").c_str ();
                    string menu_function = db3->sql_field_value ("menu_function").c_str ();
                    string menu_schemalib = db3->sql_field_value ("menu_schema_lib").c_str ();
                    string menu_schemareq = db3->sql_field_value ("menu_schema_req").c_str ();
                    //////////////////////////
                    //  Menu active???
                    sql.clear();
                    sql.str(string());
                    sql << "select   is_active from tg_group_module "
                        << "where    module_id = " << module_id << " "
                        << "and      group_code = '" << group_code << "' "
                        << "and      menu_id = " << menu_id << " ";
                    dbcheck->sql_reset ();
                    if (!dbcheck->sql_result (sql.str ().c_str ()))   {
                        _js->_log->logmsg("cyw_tree::mainmenu", db3->errordb ().c_str ());
                        return _js->_util->json_error ("Unable to retrieve the menu flag");
                    }
                    string is_active = dbcheck->sql_field_value ("is_active").c_str ();
                    //////////////////////////
                    //  Menu link
                    if (menu_library.size () < 1)
                        url  = _js->_html->link (menu_page);
                    else  {
                        string libtmp, libpath = _js->_ini->get_value("GENERAL","CGIPATH");
                        if (libpath.length () > 0)  {
                            libtmp  = libpath;
                            libtmp += menu_library;
                            menu_library = libtmp;
                            libtmp  = libpath;
                            libtmp += menu_schemalib;
                            menu_schemalib = libtmp;
                        }
                        url  = _js->_html->link (menu_library, menu_function);
                    }
                    //url  = menu_page;
                    url += "&module_id=";
                    url += module_id;
                    url += "&category_id=";
                    url += category_id;
                    url += "&menu_id=";
                    url += menu_id;
                    url += "&schema_name=";
                    url += menu_schema;
                    url += "&schema_library=";
                    url += menu_library;
                    url += "&schema_request=";
                    url += menu_function;
                    url += "&menu_schemalib=";
                    url += menu_schemalib;
                    url += "&menu_schemareq=";
                    url += menu_schemareq;
                    ///////////////////////////////
                    //  Menu entry
                    id  = module_id;
                    id += "-";
                    id += category_id;
                    id += "-";
                    id += menu_id;
                    jmenu [nmenu]["id"] = id;
                    jmenu [nmenu]["type"] = "menu";
                    jmenu [nmenu]["text"] = menu_name;
                    jmenu [nmenu]["script"] = menu_script;
                    jmenu [nmenu]["checked"] = is_active;
                    jmenu [nmenu]["url"] = url;

                    nmenu++;
                    db3->sql_next ();
                }
                if (nmenu > 0)
                    jcategory[ncategory]["children"]=jmenu;
                ncategory++;
                db2->sql_next ();
            }
            if (ncategory > 0)
                jmodule[nmodule]["children"]=jcategory;
            nmodule++;
            db1->sql_next ();
        }
        jroot = jmodule;
    }
    ///////////////////////////////////////
    //  Success
    sql.clear ();
    sql.str(string(""));
    sql << jroot << endl;
    return sql.str ();
}
/*******************************************************************
      FUNCTION:          page_credentials
   DESCRIPTION:          User credentials
     ARGUMENTS:          NONE
       RETURNS:          JSON tree hierarchy
 *******************************************************************/
string                   cyindex::page_credentials ()
{
    _js->_log->logmsg(".......Credentials:", "Entering..");
    //////////////////////////////////////
    //  Retrieve argument(s)
    string username = _js->_cgi->form ("username");
    string password = _js->_cgi->form ("password");

    /////////////////////////////////////
    // Get the current date
    string today;
    _js->_util->int_date(today,0);

    ///////////////////////////////////////
    //  Database
    CYDbSql* db = _js->_cydb->dbconn (_inisection);
    if (nullptr == db)
        return (_js->_html->fatal_error(
            "Unable to create the database connection",
            db->errordb()));
    //////////////////////////////////////
    //  Assemble URLs
    string urlmenu  = _js->_html->link (_js->_cgi_universal,"treemenu");
    string urlabout = _js->_html->link (_js->_cgi_universal,"about");
    //////////////////////////////////////
    //  Validate credentials
    string tmp, sql;

    sql  = "select    a.retry_count, a.user_locked, b.min_pass_len, ";
    sql += "b.passwd_history, b.retry_attempts, a.expire_date ";
    sql += "from  tg_user a, tg_user_group b ";
    sql += "where a.group_code = b.group_code ";
    sql += "and   a.username = ";
    sql += db->sql_bind(1, _js->_session->_username);
    if (!db->sql_result(sql,true))
                return (_js->_html->redirect(false,"default","", db->errordb(),_js->_cgi_universal));

    string retry_count = db->sql_field_value("retry_count");
    string user_locked = db->sql_field_value("user_locked");
    string retry_attempts = db->sql_field_value("retry_attempts");
    string expire_date = db->sql_field_value("expire_date");

    if(expire_date.size() == 0) expire_date = "30001231";

    if(user_locked == "1"){
       return (_js->_html->redirect(false,"default","",
                           "Your account is locked please contact administrator<br>to reset your account.",_js->_cgi_universal));
    }

    if(today >= expire_date){
        return (_js->_html->redirect(false,"default","",
                            "Your account is expired.",_js->_cgi_universal));
    }

    if (!_js->_session->session_new(username,password))  {
        _js->_log->logmsg("....SESSION CREATE:", "FAIL......");
        if(retry_count == retry_attempts){
            db->sql_reset();
            sql  = "update tg_user set user_locked = 1 ";
            sql += "where username = ";
            sql += db->sql_bind(1, _js->_session->_username);

            if (!db->sql_only(sql,true))
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
            if (!db->sql_commit())
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
        }
        if(retry_count == ""){
            db->sql_reset();
            sql  = "update tg_user set retry_count = 1 ";
            sql += "where username = ";
            sql += db->sql_bind(1, _js->_session->_username);

            if (!db->sql_only(sql,true))
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
            if (!db->sql_commit())
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
         } else {
            db->sql_reset();
            sql  = "update tg_user set retry_count = retry_count + 1 ";
            sql += "where username = ";
            sql += db->sql_bind(1, _js->_session->_username);

            if (!db->sql_only(sql,true))
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
            if (!db->sql_commit())
                return (_js->_html->fatal_error("Unable to update the record", db->errordb()));
        }

        return (_js->_html->redirect(false,"default","",
                _js->_session->session_error (),_js->_cgi_universal));

    }

    _js->_session->session_info (username);
    urlmenu += "&group_code=";
    urlmenu += _js->_session->_group_code;
    //////////////////////////////////////
    //  Main page
    stringstream out;
    out << _js->_html->header (_js->_ini->get_value ("GENERAL","TITLE"))
        << "</head>" << endl
        << "<body>" << endl
        << _js->_html->form (0,"frmexit","default","post","","",true,_js->_cgi_universal)
        << "  <div id=\"wrapper\" class=\"col-md-12 dropdown\" style=\"background: #eeeeee;\">" << endl
        << "    <button class=\"btn btn-lg dropdown-toggle\" type=\"button\"" << endl
        << "            style=\"background-color: transparent;\" id=\"menu\"" << endl
        << "            data-toggle=\"collapse\" href=\"#treemenu\">" << endl
        << "            <span class=\"fa fa-bars\">" << endl
        << "              <span class=\"caret\"></span>" << endl
        << "            </span>" << endl
        << "    </button>" << endl
        << "    <ul class=\"dropdown-menu\" id=\"treemenu\">" << endl
        << "      <li>" << endl
        << "        <div id=\"tree\" name=\"tree\" style=\"width: 240px;\"></div>" << endl
        << "      </li>" << endl
        << "    </ul>" << endl
        << "    <button class=\"btn btn-sm dropdown-toggle\" type=\"button\"" << endl
        << "            style=\"background-color: transparent;\" id=\"user\"" << endl
        << "            data-toggle=\"collapse\" href=\"#userinfo\">" << endl
        << "            <span class=\"fa fa-user fa-lg\">" << endl
        << "              <span class=\"caret\"></span>" << endl
        << "            </span>" << endl
        << "    </button>" << endl
        << "    <ul class=\"dropdown-menu\" id=\"userinfo\">" << endl
        << "      <div style=\"width: 250px; margin-left: 5px;\">" << endl
        << "        <div class=\"form-group\">" << endl
        << "          <label><b>Name:</b></label><br>" << endl
        << "            " << _js->_session->_first_name << " "
                          << _js->_session->_middle_name << " "
                          << _js->_session->_last_name << " "
        << "        </div>" << endl
        << "        <div class=\"form-group\">" << endl
        << "          <label><b>Company:</b></label><br>" << endl
        << "            " << _js->_session->_company_name << " "
        << "        </div>" << endl
        << "        <div class=\"form-group\">" << endl
        << "          <label><b>Branch:</b></label><br>" << endl
        << "            " << _js->_session->_branch_name << " "
        << "        </div>" << endl
        << "        <div class=\"form-group\">" << endl
        << "          <label><b>Security Group:</b></label><br>" << endl
        << "            " << _js->_session->_group_name << " "
        << "        </div>" << endl
        << "</form>" << endl
        << _js->_html->form (0,"frmpassword","default","post","","",true, "/cyware/changepassword.cgi")
        << "        <div class=\"form-group\">" << endl
        << "          <label><b>Manage Password:</b></label><br>" << endl
        << "           <button type=\"submit\" form=\"frmpassword\" class=\"btn btn-primary\">" << endl
        << "              Change Password"
        << "           </button>"
        << "        </div>" << endl
        << "      </div>" << endl
        << "</form>" << endl
        << "    </ul>" << endl
        << "    <button class=\"btn btn-lg btn-default\" type=\"submit\"" << endl
        << "            style=\"float:right; background-color: transparent; border-color: transparent;\">" << endl
        << "            <span class=\"fa fa-sign-out\"></span>" << endl
        << "    </button>" << endl
        << "  </div>" << endl
        << "<iframe name=\"screen\" id=\"screen\" frameborder=\"0\" allowfullscreen" << endl
        << "        style=\"width: 100%; height: 8800px; margin-left: 0px;\" src=\"" << urlabout << "\">" << endl
        << "</iframe>" << endl
        << "<script type=\"text/javascript\">" << endl
        << "  $(document).ready(function () {" << endl

        << "    var tree = $('#tree').tree({" << endl
        << "                  primaryKey: 'id'," << endl
        << "                  uiLibrary: 'bootstrap4'," << endl
        << "                  iconsLibrary: 'fontawesome'," << endl
        << "                  dataSource: '" << urlmenu << "'," << endl
        << "                  checkboxes: false," << endl
        << "                  dataBound: function (e) {" << endl
        << "                    //tree.expandAll ();" << endl
        << "                  }" << endl
        << "  });" << endl
        << "  $('#tree').on('select', function (e, node, id)  {" << endl
        << "    var data, frame;" << endl
        << "    data = tree.getDataById (id);" << endl
        << "    frame = document.getElementById ('screen');" << endl
        << "    if (data.url.length > 0)  {" << endl
        << "      frame.src = data.url;" << endl
        << "      setTimeout(function() {" << endl
        << "        $('#menu').trigger('click');" << endl
        << "      }, 1000);" << endl
        << "      $(\"#wrapper\")[0].scrollIntoView();" << endl
        << "    }" << endl
        << "  });" << endl

        << "});" << endl
        << "</script>" << endl
        << "</body>" << endl
        << "</html>" << endl;
    return (out.str ());
}
