/*
 * Copyright (C) Tildeslash Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.  
 */

#include "config.h"

#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#include "monit.h"
#include "event.h"
#include "net.h"
#include "alert.h"

// libmonit
#include "system/Time.h"
#include "util/Str.h"


/**
 *  Implementation of the alert module
 *
 *  @file
 */


/* -------------------------------------------------------------- Prototypes */


static void copy_mail(Mail_T, Mail_T);
static void replace_bare_linefeed(Mail_T *);
static void substitute(Mail_T *, Event_T);


/* ------------------------------------------------------------------ Public */


/**
 * Notify registred users about the event
 * @param E An Event object
 * @return If failed, return HANDLER_ALERT flag or HANDLER_SUCCEEDED if succeeded
 */
int handle_alert(Event_T E) {
  Service_T s;
  int rv = HANDLER_SUCCEEDED;

  ASSERT(E);

  s= Event_get_source(E);
  if(!s) {
    LogError("Aborting alert\n");
    return rv;
  }

  if(s->maillist || Run.maillist) {
    Mail_T m;
    Mail_T n;
    Mail_T list= NULL;
    /*
     * Build a mail-list with local recipients that has registered interest
     * for this event.
     */
    for(m= s->maillist; m; m= m->next) {
      
      if(
        /* particular event notification type is allowed for given recipient */
        IS_EVENT_SET(m->events, Event_get_id(E)) &&
        (
          /* state change notification is sent always */
          E->state_changed       ||
          /* in the case that the state is failed for more cycles we check
           * whether we should send the reminder */
          (E->state && m->reminder && E->count % m->reminder == 0)
        )
      )
      {
        Mail_T tmp= NULL;

        NEW(tmp);
        copy_mail(tmp, m);
        substitute(&tmp, E);
        replace_bare_linefeed(&tmp);
        tmp->next= list;
        list= tmp;

        DEBUG("%s notification is sent to %s\n", Event_get_description(E), m->to);

      }

    }

    /*
     * Build a mail-list with global recipients that has registered interest
     * for this event. Recipients which are defined in the service localy
     * overrides the same recipient events which are registered globaly.
     */
    for(m= Run.maillist; m; m= m->next) {
      int skip= FALSE;

      for(n= s->maillist; n; n= n->next) {
        if(IS(m->to, n->to)) {
          skip= TRUE;
          break;
        }
      }

      if(
        /* the local service alert definition has not overrided the global one */
        !skip &&
        /* particular event notification type is allowed for given recipient */
        IS_EVENT_SET(m->events, Event_get_id(E)) &&
        (
          /* state change notification is sent always */
          E->state_changed       ||
          /* in the case that the state is failed for more cycles we check
           * whether we should send the reminder */
          (E->state && m->reminder && E->count % m->reminder == 0)
        )
      )
      {

        Mail_T tmp= NULL;

        NEW(tmp);
        copy_mail(tmp, m);
        substitute(&tmp, E);
        replace_bare_linefeed(&tmp);
        tmp->next= list;
        list= tmp;

        DEBUG("%s notification is sent to %s\n", Event_get_description(E), m->to);

      }

    }

    if(list) {

      if(!sendmail(list))
        rv = HANDLER_ALERT;
      gc_mail_list(&list);

    }

  }

  return rv;

}


static void substitute(Mail_T *m, Event_T e) {
  char timestamp[STRLEN];

  ASSERT(m && e);

  Util_replaceString(&(*m)->from,    "$HOST", Run.localhostname);
  Util_replaceString(&(*m)->subject, "$HOST", Run.localhostname);
  Util_replaceString(&(*m)->message, "$HOST", Run.localhostname);
  
  Time_string(e->collected.tv_sec, timestamp);
  Util_replaceString(&(*m)->subject, "$DATE", timestamp);
  Util_replaceString(&(*m)->message, "$DATE", timestamp);

  Util_replaceString(&(*m)->subject, "$SERVICE", Event_get_source_name(e));
  Util_replaceString(&(*m)->message, "$SERVICE", Event_get_source_name(e));

  Util_replaceString(&(*m)->subject, "$EVENT", Event_get_description(e));
  Util_replaceString(&(*m)->message, "$EVENT", Event_get_description(e));

  Util_replaceString(&(*m)->subject, "$DESCRIPTION", NVLSTR(Event_get_message(e)));
  Util_replaceString(&(*m)->message, "$DESCRIPTION", NVLSTR(Event_get_message(e)));

  Util_replaceString(&(*m)->subject, "$ACTION", Event_get_action_description(e));
  Util_replaceString(&(*m)->message, "$ACTION", Event_get_action_description(e));
}


static void copy_mail(Mail_T n, Mail_T o) {
  ASSERT(n && o);
  
  n->to= Str_dup(o->to);
  n->from=
      o->from?
      Str_dup(o->from):
      Run.MailFormat.from?
      Str_dup(Run.MailFormat.from):
      Str_dup(ALERT_FROM);
  n->replyto = 
      o->replyto?
      Str_dup(o->replyto):
      Run.MailFormat.replyto?
      Str_dup(Run.MailFormat.replyto):
      NULL;
  n->subject=
      o->subject?
      Str_dup(o->subject):
      Run.MailFormat.subject?
      Str_dup(Run.MailFormat.subject):
      Str_dup(ALERT_SUBJECT);
  n->message=
      o->message?
      Str_dup(o->message):
      Run.MailFormat.message?
      Str_dup(Run.MailFormat.message):
      Str_dup(ALERT_MESSAGE);
}


static void replace_bare_linefeed(Mail_T *m) {
  Util_replaceString(&(*m)->message, "\r\n", "\n");
  Util_replaceString(&(*m)->message, "\n", "\r\n");
}
