/*
 * BRLTTY - A background process providing access to the console screen (when in
 *          text mode) for a blind person using a refreshable braille display.
 *
 * Copyright (C) 1995-2023 by The BRLTTY Developers.
 *
 * BRLTTY comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU Lesser General Public License, as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any
 * later version. Please see the file LICENSE-LGPL for details.
 *
 * Web Page: http://brltty.app/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

#include "prologue.h"

#include <stdio.h>
#include <string.h>

#include "log.h"
#include "strfmt.h"
#include "file.h"
#include "dynld.h"
#include "drivers.h"

int
isDriverAvailable (const char *code, const char *codes) {
  int length = strlen(code);
  const char *string = codes;

  while ((string = strstr(string, code))) {
    if (((string == codes) || (string[-1] == ' ')) &&
        (!string[length] || (string[length] == ' '))) {
      return 1;
    }

    string += length;
  }

  return 0;
}

int
isDriverIncluded (const char *code, const DriverEntry *table) {
  while (table->address) {
    if (strcmp(code, table->definition->code) == 0) return 1;
    ++table;
  }
  return 0;
}

int
haveDriver (const char *code, const char *codes, const DriverEntry *table) {
  return (table && table->address)? isDriverIncluded(code, table):
                                    isDriverAvailable(code, codes);
}

const char *
getDefaultDriver (const DriverEntry *table) {
  return (table && table[0].address && !table[1].address)? table[0].definition->code: NULL;
}

static int
isDriverCode (const char *code, const DriverDefinition *definition) {
  if (strcmp(code, definition->code) == 0) return 1;
  return 0;
}

const void *
loadDriver (
  const char *driverCode, void **driverObject,
  const char *driverDirectory, const DriverEntry *driverTable,
  const char *typeName, char typeLetter, const char *symbolPrefix,
  const void *nullAddress, const DriverDefinition *nullDefinition
) {
  const void *driverAddress = NULL;
  *driverObject = NULL;

  if (!driverCode || !*driverCode) {
    if (driverTable)
      if (driverTable->address)
        return driverTable->address;
    return nullAddress;
  }

  if (isDriverCode(driverCode, nullDefinition)) return nullAddress;

  if (driverTable) {
    const DriverEntry *driverEntry = driverTable;
    while (driverEntry->address) {
      if (isDriverCode(driverCode, driverEntry->definition)) return driverEntry->address;
      ++driverEntry;
    }
  }

#ifdef ENABLE_SHARED_OBJECTS
  {
    char *libraryPath;
    const int libraryNameLength = strlen(MODULE_NAME) + strlen(driverCode) + strlen(MODULE_EXTENSION) + 3;
    char libraryName[libraryNameLength];
    snprintf(libraryName, libraryNameLength, "%s%c%s.%s",
             MODULE_NAME, typeLetter, driverCode, MODULE_EXTENSION);

    if ((libraryPath = makePath(driverDirectory, libraryName))) {
      void *libraryHandle = loadSharedObject(libraryPath);

      if (libraryHandle) {
        const int driverSymbolLength = strlen(symbolPrefix) + 8 + strlen(driverCode) + 1;
        char driverSymbol[driverSymbolLength];
        snprintf(driverSymbol, driverSymbolLength, "%s_driver_%s",
                 symbolPrefix, driverCode);

        if (findSharedSymbol(libraryHandle, driverSymbol, &driverAddress)) {
          *driverObject = libraryHandle;

          {
            const void *versionAddress = NULL;
            const int versionSymbolLength = strlen(symbolPrefix) + 9 + strlen(driverCode) + 1;
            char versionSymbol[versionSymbolLength];
            snprintf(versionSymbol, versionSymbolLength, "%s_version_%s",
                     symbolPrefix, driverCode);

            if (findSharedSymbol(libraryHandle, versionSymbol, &versionAddress)) {
              const char *actualVersion = versionAddress;
              static const char *expectedVersion = DRIVER_VERSION_STRING;

              if (strcmp(actualVersion, expectedVersion) != 0) {
                logMessage(LOG_WARNING,
                  "%s driver version mismatch: %s: Expected:%s Actual%s",
                  typeName, driverCode,
                  expectedVersion, actualVersion
                );
              }
            } else {
              logMessage(LOG_WARNING,
                "cannot find %s driver version symbol: %s: %s",
                typeName, driverCode, versionSymbol
              );
            }
          }
        } else {
          logMessage(LOG_ERR,
            "cannot find %s driver symbol: %s",
            typeName, driverSymbol
          );

          unloadSharedObject(libraryHandle);
          driverAddress = NULL;
        }
      } else {
        logMessage(LOG_ERR,
          "cannot load %s driver: %s",
          typeName, libraryPath
        );
      }

      free(libraryPath);
    }
  }
#endif /* ENABLE_SHARED_OBJECTS */

  return driverAddress;
}

void
identifyDriver (
  const char *type,
  const DriverDefinition *definition,
  int full
) {
  {
    char buffer[0X100];
    STR_BEGIN(buffer, sizeof(buffer));

    STR_PRINTF(
      "%s Driver: %s [%s]",
      type, definition->code, definition->name
    );

    if (definition->version && *definition->version) {
      STR_PRINTF(" Version:%s", definition->version);
    }

    if (full) {
      STR_PRINTF(" (compiled on %s at %s)", definition->date, definition->time);
    }

    STR_END;
    logMessage(LOG_NOTICE, "%s", buffer);
  }

  if (full) {
    if (definition->developers && *definition->developers) {
      logMessage(LOG_INFO, "   Developed by %s", definition->developers);
    }
  }
}
