"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.finishMaintenanceWindow = finishMaintenanceWindow;
var _moment = _interopRequireDefault(require("moment"));
var _boom = _interopRequireDefault(require("@hapi/boom"));
var _generate_maintenance_window_events = require("../../lib/generate_maintenance_window_events");
var _get_maintenance_window_date_and_status = require("../../lib/get_maintenance_window_date_and_status");
var _common = require("../../../../../common");
var _retry_if_conflicts = require("../../../../lib/retry_if_conflicts");
var _maintenance_window = require("../../../../data/maintenance_window");
var _transforms = require("../../transforms");
var _schemas = require("./schemas");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */

async function finishMaintenanceWindow(context, params) {
  return await (0, _retry_if_conflicts.retryIfConflicts)(context.logger, `maintenanceWindowClient.finish('${params.id})`, async () => {
    return await finishWithOCC(context, params);
  });
}
async function finishWithOCC(context, params) {
  const {
    savedObjectsClient,
    getModificationMetadata,
    logger
  } = context;
  const {
    id
  } = params;
  try {
    _schemas.finishMaintenanceWindowParamsSchema.validate(params);
  } catch (error) {
    throw _boom.default.badRequest(`Error validating finish maintenance window data - ${error.message}`);
  }
  const modificationMetadata = await getModificationMetadata();
  const now = new Date();
  const expirationDate = _moment.default.utc(now).add(1, 'year').toDate();
  try {
    const {
      attributes,
      version,
      id: fetchedId
    } = await (0, _maintenance_window.getMaintenanceWindowSo)({
      id,
      savedObjectsClient
    });
    const maintenanceWindow = (0, _transforms.transformMaintenanceWindowAttributesToMaintenanceWindow)({
      attributes,
      id: fetchedId
    });

    // Generate new events with new expiration date
    const newEvents = (0, _generate_maintenance_window_events.generateMaintenanceWindowEvents)({
      rRule: maintenanceWindow.rRule,
      duration: maintenanceWindow.duration,
      expirationDate: expirationDate.toISOString()
    });

    // Merge it with the old events
    const events = (0, _generate_maintenance_window_events.mergeEvents)({
      newEvents,
      oldEvents: maintenanceWindow.events
    });

    // Find the current event and status of the maintenance window
    const {
      status,
      index
    } = (0, _get_maintenance_window_date_and_status.getMaintenanceWindowDateAndStatus)({
      events,
      dateToCompare: now,
      expirationDate
    });

    // Throw if the maintenance window is not running, or event doesn't exist
    if (status !== _common.MaintenanceWindowStatus.Running) {
      throw _boom.default.badRequest('Cannot finish maintenance window that is not running');
    }
    if (typeof index !== 'number' || !events[index]) {
      throw _boom.default.badRequest('Cannot find maintenance window event to finish');
    }

    // Update the running event to finish now
    const eventToFinish = {
      gte: events[index].gte,
      lte: now.toISOString()
    };

    // Update the events with the new finished event
    const eventsWithFinishedEvent = [...events];
    eventsWithFinishedEvent[index] = eventToFinish;
    const updateMaintenanceWindowAttributes = (0, _transforms.transformMaintenanceWindowToMaintenanceWindowAttributes)({
      ...maintenanceWindow,
      events: eventsWithFinishedEvent,
      expirationDate: expirationDate.toISOString(),
      updatedAt: modificationMetadata.updatedAt,
      updatedBy: modificationMetadata.updatedBy
    });
    const result = await (0, _maintenance_window.updateMaintenanceWindowSo)({
      id: fetchedId,
      savedObjectsClient,
      updateMaintenanceWindowAttributes,
      savedObjectsUpdateOptions: {
        version
      }
    });
    return (0, _transforms.transformMaintenanceWindowAttributesToMaintenanceWindow)({
      attributes: {
        ...attributes,
        ...result.attributes
      },
      id: result.id
    });
  } catch (e) {
    const errorMessage = `Failed to finish maintenance window by id: ${id}, Error: ${e}`;
    logger.error(errorMessage);
    throw _boom.default.boomify(e, {
      message: errorMessage
    });
  }
}