<?php

register_deploydashboards();
function register_deploydashboards() {

    $component_args = array(

        COMPONENT_NAME              => 'deploydashboards',
        COMPONENT_TITLE             => _('Deploy Dashboards'),
        COMPONENT_VERSION           => '4.0.1',
        COMPONENT_DATE              => '10/04/2017',
        COMPONENT_AUTHOR            => 'Nagios Enterprises, LLC',
        COMPONENT_DESCRIPTION       => _('Escalate your dashboards to deploy status, allowing anyone to use them.'),
        COMPONENT_REQUIRES_VERSION  => 3990,

        COMPONENT_FUNCTION          => 'deploydashboards_successful_registration',
    );

    register_component($component_args);
}

function deploydashboards_successful_registration() {

    register_callback(CALLBACK_MENU_INITIALIZED, 'register_deploydashboards_menu');
    register_callback(CALLBACK_GET_DASHBOARD, 'check_synced_dashboards');
}


function register_deploydashboards_menu($cb, &$menu) {

    if (is_admin()) {

        $menu->add_link_spacer('dashboards-tools');
        $menu->add_link(menu_link(_('Deploy Dashboards'), get_components_base_url() . 'deploydashboards/deploydashboards.php', '', '', 'fa-globe'), 'dashboards-tools');
    }
}


// actually deploy the dashboard
// by default, this creates a new dashboard based on an existing one
// if you specify the deployed_id, then it simply reclones the original to that dashboard..
function deploy_dashboard_to_user_or_dashboard($dashboard_id, $user_id, $name, $sync, $home, $screen, $deployed_id = null) {

    // by the time this function is called, dashboard_id, user_id have been checked for validity
    // name and sync are simply supplied, but those values are already accurate as well
    // having said that, there is no escaping checking them again...

    // create the new dashboard as a copy of the specified one and get the id
    $dashboard = get_dashboard($dashboard_id);
    if (!$dashboard)
        return false;

    if ($deployed_id === null) {

        if ($sync == true)
            $sync = $dashboard_id;
        else
            $sync = 0;

        $deployed_id = add_dashboard($name, $user_id, $sync, $home, $dashboard['show_in_menu'], $screen, $dashboard['bgcolor']);
        if (!$deployed_id)
            return false;

    } else {

        // if we don't do this straight to the db, we get an endless loop of the callback checking in get_dashboard callback :)
        global $db;
        $bind_array = array(':deployed_dashboard_id' => $deployed_id);
        $deployed_dashboard = $db->exec_query('SELECT * FROM dashboards WHERE dashboard_id = :deployed_dashboard_id LIMIT 1', $bind_array);
        if (!$deployed_dashboard || !is_array($deployed_dashboard) || count($deployed_dashboard) != 1)
            return false;
    
        // delete all of the dashlets and dashlets_params so we can resync
        $delete_dashlets_params = $db->exec_query(
            'DELETE FROM dashlets_params WHERE dashlet_id IN (SELECT dashlet_id FROM dashlets WHERE dashboard_id = :deployed_dashboard_id)', $bind_array);
        $delete_dashlets = $db->exec_query(
            'DELETE FROM dashlets WHERE dashboard_id = :deployed_dashboard_id', $bind_array);

        // something weird happened...
        if ($delete_dashlets_params === false || $delete_dashlets === false)
            return false;
    }

    $dashlets = get_dashboard_dashlets($dashboard_id);
    if (is_array($dashlets)) {
        foreach ($dashlets as $dashlet) {

            $dashlet_name = $dashlet[DASHLET_NAME];
            $dashlet_settings = array(
                DASHLET_LOAD_URL    => $dashlet[DASHLET_LOAD_URL],
                DASHLET_TITLE       => $dashlet[DASHLET_TITLE],
                DASHLET_PINNED      => $dashlet[DASHLET_PINNED],
                DASHLET_SHOW_TITLE  => $dashlet[DASHLET_SHOW_TITLE],
                DASHLET_PADDING     => $dashlet[DASHLET_PADDING],
                DASHLET_BGCOLOR     => $dashlet[DASHLET_BGCOLOR],
                DASHLET_OPACITY     => $dashlet[DASHLET_OPACITY],
                DASHLET_REFRESH     => $dashlet[DASHLET_REFRESH],
                DASHLET_WIDTH       => $dashlet[DASHLET_WIDTH],
                DASHLET_HEIGHT      => $dashlet[DASHLET_HEIGHT],
                DASHLET_X           => $dashlet[DASHLET_X],
                DASHLET_Y           => $dashlet[DASHLET_Y],
                DASHLET_ZINDEX      => $dashlet[DASHLET_ZINDEX],
                );

            $dashlet_params = array();
            if (isset($dashlet[DASHLET_PARAMS]) && is_array($dashlet[DASHLET_PARAMS])) {

                foreach ($dashlet[DASHLET_PARAMS] as $param => $param_data) {

                    if (isset($param_data['val']))
                        $dashlet_params[$param] = $param_data['val'];
                }
            }

            if (add_dashlet($dashlet_name, $deployed_id, $dashlet_settings, $dashlet_params, $user_id) == false)
                return false;
        }
    }

    return true;
}


// we need to update synced dashboards
function check_synced_dashboards($cb, $cbargs) {

    // if sync isn't set or is 0, we don't care about it
    if (empty($cbargs['sync']))
        return true;

    $deployed_dashboard_id = $cbargs['dashboard_id'];
    $deployed_dashboard_name = $cbargs['dashboard_name'];
    $original_dashboard_id = $cbargs['sync'];

    // we use our own queries here since get_dashboards cares about users checking
    // dashboards that don't belong to them..
    global $db;

    $original_bind_array = array(':original_dashboard_id' => $original_dashboard_id);
    $deployed_bind_array = array(':deployed_dashboard_id' => $deployed_dashboard_id);

    $original_dashboard = $db->exec_query('SELECT * FROM dashboards WHERE dashboard_id = :original_dashboard_id LIMIT 1', $original_bind_array);

    // if the original dashboard is gone, then there is nothing to sync
    if (!$original_dashboard || !is_array($original_dashboard))
        return true;

    $original_dashboard = $original_dashboard[0];

    // we actually just update the bgcolor and show_in_menu no matter what..
    update_dashboard($deployed_dashboard_id, $dashboard_name = null, $original_dashboard['show_in_menu'], $show_in_menu = null, $original_dashboard['bgcolor']);

    // if we made it this far, we need to actually get the data and check to see if it needs to be synced
    // we do this by serializing the arrays, hashing that, and then comparing them
    // it may seem unecessary, but reads are less expensive than writes

    $original_dashlets = $db->exec_query(
        'SELECT * FROM dashlets WHERE dashboard_id = :original_dashboard_id', $original_bind_array);
    $original_dashlets_params = $db->exec_query(
        'SELECT * FROM dashlets_params WHERE dashlet_id IN (SELECT dashlet_id FROM dashlets WHERE dashboard_id = :original_dashboard_id)', $original_bind_array);

    $deployed_dashlets = $db->exec_query(
        'SELECT * FROM dashlets WHERE dashboard_id = :deployed_dashboard_id', $deployed_bind_array);
    $deployed_dashlets_params = $db->exec_query(
        'SELECT * FROM dashlets_params WHERE dashlet_id IN (SELECT dashlet_id FROM dashlets WHERE dashboard_id = :deployed_dashboard_id)', $deployed_bind_array);

    // something went wrong ....
    if ($original_dashlets === false || $original_dashlets_params === false || $deployed_dashlets === false || $deployed_dashlets_params === false)
        return false;

    // unset any data that we know will be different between the original and deployed arrays
    $original_dashlets = array_map('unset_dashlet_id', $original_dashlets);
    $original_dashlets_params = array_map('unset_dashlet_id', $original_dashlets_params);
    $deployed_dashlets = array_map('unset_dashlet_id', $deployed_dashlets);
    $deployed_dashlets_params = array_map('unset_dashlet_id', $deployed_dashlets_params);

    $original_dashlets = md5(print_r($original_dashlets, true));
    $original_dashlets_params = md5(print_r($original_dashlets_params, true));
    $deployed_dashlets = md5(print_r($deployed_dashlets, true));
    $deployed_dashlets_params = md5(print_r($deployed_dashlets_params, true));

    if ($original_dashlets == $deployed_dashlets && $original_dashlets_params == $deployed_dashlets_params)
        return true;

    // if we made it this far, then we need to resync the dashboards...
    // we don't we-sync home/screen since that could have been changed somewhere down the line..
    deploy_dashboard_to_user_or_dashboard($original_dashboard_id, intval($_SESSION['user_id']), $deployed_dashboard_name, true, $home = null, $screen = null, $deployed_dashboard_id);
}

// the dashlet/dashboard ids are GOING to be different, we can't let that affect the hashing..
function unset_dashlet_id($row) {

    if (isset($row['dashlet_id']))
        unset($row['dashlet_id']);

    if (isset($row['dashboard_id']))
        unset($row['dashboard_id']);

    return $row;
}