/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <winmeta.h>
#include "WindowsEventLog.h"
#include "UnicodeConversion.h"
#include "utils/Deleters.h"
#include "utils/ScopeGuard.h"
#include <algorithm>

namespace org {
namespace apache {
namespace nifi {
namespace minifi {
namespace wel {

void WindowsEventLogMetadataImpl::renderMetadata() {
  DWORD status = ERROR_SUCCESS;
  DWORD dwBufferSize = 0;
  DWORD dwBufferUsed = 0;
  DWORD dwPropertyCount = 0;
  std::unique_ptr< EVT_VARIANT, utils::FreeDeleter> rendered_values;

  auto context = EvtCreateRenderContext(0, NULL, EvtRenderContextSystem);
  if (context == NULL) {
    return;
  }
  utils::ScopeGuard contextGuard([&context](){
    EvtClose(context);
  });
  if (!EvtRender(context, event_ptr_, EvtRenderEventValues, dwBufferSize, nullptr, &dwBufferUsed, &dwPropertyCount))
  {
    if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
    {
      dwBufferSize = dwBufferUsed;
      rendered_values = std::unique_ptr<EVT_VARIANT, utils::FreeDeleter>((PEVT_VARIANT)(malloc(dwBufferSize)));
      if (rendered_values)
      {
        EvtRender(context, event_ptr_, EvtRenderEventValues, dwBufferSize, rendered_values.get(), &dwBufferUsed, &dwPropertyCount);
      }
    }
    else {
      return;
    }

    if (ERROR_SUCCESS != (status = GetLastError()))
    {
      return;
    }
  }

  event_timestamp_ = static_cast<PEVT_VARIANT>( rendered_values.get())[EvtSystemTimeCreated].FileTimeVal;

  SYSTEMTIME st;
  FILETIME ft;

  ft.dwHighDateTime = (DWORD)((event_timestamp_ >> 32) & 0xFFFFFFFF);
  ft.dwLowDateTime = (DWORD)(event_timestamp_ & 0xFFFFFFFF);

  FileTimeToSystemTime(&ft, &st);
  std::stringstream datestr;

  std::string period = "AM";
  auto hour = st.wHour;
  if (hour >= 12 && hour < 24)
    period = "PM";
  if (hour > 12)
    hour -= 12;
  if (hour == 0)
    hour = 12;
  datestr << st.wMonth << "/" << st.wDay << "/" << st.wYear << " " << std::setfill('0') << std::setw(2) << hour << ":" << std::setfill('0') << std::setw(2) << st.wMinute << ":" << std::setfill('0') << std::setw(2) << st.wSecond << " " << period;
  event_timestamp_str_ = datestr.str();
  auto level = static_cast<PEVT_VARIANT>(rendered_values.get())[EvtSystemLevel];
  auto keyword = static_cast<PEVT_VARIANT>(rendered_values.get())[EvtSystemKeywords];
  if (level.Type == EvtVarTypeByte) {
    switch (level.ByteVal)
    {
      case WINEVENT_LEVEL_CRITICAL:
      case WINEVENT_LEVEL_ERROR:
        event_type_ = "Error";
        event_type_index_ = 1;
        break;
      case WINEVENT_LEVEL_WARNING:
        event_type_ = "Warning";
        event_type_index_ = 2;
        break;
      case WINEVENT_LEVEL_INFO:
      case WINEVENT_LEVEL_VERBOSE:
        event_type_ = "Information";
        event_type_index_ = 4;
        break;
      default:
        event_type_index_ = 0;
    };

  }
  else {
    event_type_ = "N/A";
  }

  if (keyword.UInt64Val & WINEVENT_KEYWORD_AUDIT_SUCCESS) {
    event_type_ = "Success Audit";
    event_type_index_ = 8;
  } else if (keyword.UInt64Val & EVENTLOG_AUDIT_FAILURE) {
    event_type_ = "Failure Audit";
    event_type_index_ = 16;
  }
}

std::string WindowsEventLogMetadataImpl::getEventData(EVT_FORMAT_MESSAGE_FLAGS flags) const {
  LPWSTR string_buffer = NULL;
  DWORD string_buffer_size = 0;
  DWORD string_buffer_used = 0;
  DWORD result = 0;

  std::string event_data;

  if (metadata_ptr_ == NULL | event_ptr_ == NULL) {
    return event_data;
  }

  if (!EvtFormatMessage(metadata_ptr_, event_ptr_, 0, 0, NULL, flags, string_buffer_size, string_buffer, &string_buffer_used)) {
    result = GetLastError();
    if (ERROR_INSUFFICIENT_BUFFER == result) {
      string_buffer_size = string_buffer_used;

      string_buffer = (LPWSTR) malloc(string_buffer_size * sizeof(WCHAR));

      if (string_buffer) {

        if ((EvtFormatMessageKeyword == flags))
          string_buffer[string_buffer_size - 1] = L'\0';

        EvtFormatMessage(metadata_ptr_, event_ptr_, 0, 0, NULL, flags, string_buffer_size, string_buffer, &string_buffer_used);
        if ((EvtFormatMessageKeyword == flags))
          string_buffer[string_buffer_used - 1] = L'\0';
        std::wstring str(string_buffer);
        event_data = std::string(str.begin(), str.end());
        free(string_buffer);
      }
    }
  }
  return event_data;
}

std::string WindowsEventLogHandler::getEventMessage(EVT_HANDLE eventHandle) const
{
  std::string returnValue;
  std::unique_ptr<WCHAR, utils::FreeDeleter> pBuffer;
  DWORD dwBufferSize = 0;
  DWORD dwBufferUsed = 0;
  DWORD status = 0;

  EvtFormatMessage(metadata_provider_, eventHandle, 0, 0, NULL, EvtFormatMessageEvent, dwBufferSize, pBuffer.get(), &dwBufferUsed);
  if (dwBufferUsed == 0) {
    return returnValue;
  }

  //  we need to get the size of the buffer
  status = GetLastError();
  if (ERROR_INSUFFICIENT_BUFFER == status) {
    dwBufferSize = dwBufferUsed;

    /* All C++ examples use malloc and even HeapAlloc in some cases. To avoid any problems ( with EvtFormatMessage calling
      free for example ) we will continue to use malloc and use a custom deleter with unique_ptr.
    '*/
    pBuffer = std::unique_ptr<WCHAR, utils::FreeDeleter>((LPWSTR)malloc(dwBufferSize * sizeof(WCHAR)));
    if (!pBuffer) {
      return returnValue;
    }

    EvtFormatMessage(metadata_provider_, eventHandle, 0, 0, NULL, EvtFormatMessageEvent, dwBufferSize, pBuffer.get(), &dwBufferUsed);
  }

  if (ERROR_EVT_MESSAGE_NOT_FOUND == status || ERROR_EVT_MESSAGE_ID_NOT_FOUND == status) {
    return returnValue;
  }

  // convert wstring to std::string
  return to_string(pBuffer.get());
}

void WindowsEventLogHeader::setDelimiter(const std::string &delim) {
  delimiter_ = delim;
}

std::string WindowsEventLogHeader::createDefaultDelimiter(size_t max, size_t length) const {
  if (max > length) {
    return ":" + std::string(max - length, ' ');
  }
  else {
    return ": ";
  }
}

EVT_HANDLE WindowsEventLogHandler::getMetadata() const {
  return metadata_provider_;
}

} /* namespace wel */
} /* namespace minifi */
} /* namespace nifi */
} /* namespace apache */
} /* namespace org */

