#include <stdlib.h>
#include <getopt.h>
#include <syslog.h>
#include <stdio.h>
#include <pcre.h>

#include "PatchCordProxy.h"
#include "UserDataStore.h"

#define VECTORS_COUNT        8
#define DEFAULT_USER_NUMBER  1
#define DEFAULT_LINK_NUMBER  10

#define EMPTY_STRING         ""

int main(int argc, const char* argv[])
{
  printf("\n");
  printf("CallCapture for BrandMeister DMR Master Server\n");
  printf("Copyright 2015 Artem Prilutskiy (R3ABM, cyanide.burnout@gmail.com)\n");
  printf("\n");
  
  // Start up
  
  struct option options[] =
  {
    { "expression", required_argument, NULL, 'e' },
    { "connection", required_argument, NULL, 'c' },
    { "identity",   required_argument, NULL, 'i' },
    { "network",    required_argument, NULL, 'n' },
    { "unknown",    required_argument, NULL, 'u' },
    { "link",       required_argument, NULL, 'l' },
    { NULL,         0,                 NULL, 0   }
  };

  pcre* expression = NULL;
  const char* file = NULL;
  uint32_t network = 0;
  uint32_t unknown = DEFAULT_USER_NUMBER;
  uint32_t link = DEFAULT_LINK_NUMBER;

  int position = 0;
  const char* error = NULL;

  int selection = 0;
  while ((selection = getopt_long(argc, const_cast<char* const*>(argv), "e:c:u:n:l:", options, NULL)) != EOF)
    switch (selection)
    {
      case 'e':
        expression = pcre_compile(optarg, 0, &error, &position, NULL);
        break;

      case 'c':
        file = optarg;
        break;

      case 'i':
        openlog(optarg, 0, LOG_USER);
        break;

      case 'u':
        unknown = atoi(optarg);
        break;

      case 'n':
        network = atoi(optarg);
        break;

      case 'l':
        link = atoi(optarg);
        break;
    }

  if ((expression == NULL) &&
      (error != NULL))
  {
    printf("Error compiling regular expression: %s (at %d)\n", error, position);
    return EXIT_FAILURE;
  }

  if ((expression == NULL) ||
      (network == 0) ||
      (file == NULL))
  {
    printf(
      "Usage: %s\n"
      " --expression <regular expression>\n"
      " --connection <path to configuration file>\n"
      " [--unknown <ID for unknown call-signs>]\n"
      " --network <network number>\n"
      " --link <link number>\n"
      " [--identity <identity>]\n"
      "\n"
      "Expression example:\n"
      " (?<alias>(?<call>[RU][A-Z]?[0-9][A-Z]{1,4})[^;])\n"
      "\n",
      argv[0]);
    return EXIT_FAILURE;
  }

  // Main

  UserDataStore store(file);
  PatchCordProxy proxy(network, link);

  char* line = NULL;
  size_t length = 0;
  ssize_t read;

  while ((read = getline(&line, &length, stdin)) != EOF)
  {
    syslog(LOG_DEBUG, "%s", line);

    int vectors[VECTORS_COUNT];
    int count = pcre_exec(expression, NULL, line, length, 0, 0, vectors, VECTORS_COUNT);
    if (count > 0)
    {
      const char* call = EMPTY_STRING;
      const char* alias = EMPTY_STRING;

      pcre_get_named_substring(expression, line, vectors, count, "call", &call);
      pcre_get_named_substring(expression, line, vectors, count, "alias", &alias);

      uint32_t number = store.getPrivateIDForCall(call);

      if (number == 0)
        number = unknown;

      proxy.setTalkerID(number);
      proxy.setTalkerAlias(alias);

      syslog(LOG_INFO, "*** Found call-sign: %s (ID: %d, Alias: \"%s\")", call, number, alias);

      pcre_free_substring(call);
    }
  }

  pcre_free(expression);

  return EXIT_SUCCESS;
};