"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.GraphStorage = void 0;
var _boom = _interopRequireDefault(require("@hapi/boom"));
var _cm_services = require("../../common/content_management/cm_services");
/*
 * 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.
 */

const savedObjectClientFromRequest = async ctx => {
  if (!ctx.requestHandlerContext) {
    throw new Error('Storage context.requestHandlerContext missing.');
  }
  const {
    savedObjects
  } = await ctx.requestHandlerContext.core;
  return savedObjects.client;
};
function savedObjectToGraphSavedObject(savedObject) {
  const {
    id,
    type,
    updated_at: updatedAt,
    created_at: createdAt,
    attributes: {
      title,
      description,
      version,
      kibanaSavedObjectMeta,
      wsState,
      numVertices,
      numLinks,
      legacyIndexPatternRef
    },
    references,
    error,
    namespaces
  } = savedObject;
  return {
    id,
    type,
    updatedAt,
    createdAt,
    attributes: {
      title,
      description,
      kibanaSavedObjectMeta,
      wsState,
      version,
      numLinks,
      numVertices,
      legacyIndexPatternRef
    },
    references,
    error,
    namespaces
  };
}
const SO_TYPE = 'graph-workspace';
class GraphStorage {
  constructor() {}
  async get(ctx, id) {
    const {
      utils: {
        getTransforms
      },
      version: {
        request: requestVersion
      }
    } = ctx;
    const transforms = getTransforms(_cm_services.cmServicesDefinition, requestVersion);
    const soClient = await savedObjectClientFromRequest(ctx);

    // Save data in DB
    const {
      saved_object: savedObject,
      alias_purpose: aliasPurpose,
      alias_target_id: aliasTargetId,
      outcome
    } = await soClient.resolve(SO_TYPE, id);
    const response = {
      item: savedObjectToGraphSavedObject(savedObject, false),
      meta: {
        aliasPurpose,
        aliasTargetId,
        outcome
      }
    };

    // Validate DB response and DOWN transform to the request version
    const {
      value,
      error: resultError
    } = transforms.get.out.result.down(response);
    if (resultError) {
      throw _boom.default.badRequest(`Invalid response. ${resultError.message}`);
    }
    return value;
  }
  async bulkGet() {
    // Not implemented. Graph does not use bulkGet
    throw new Error(`[bulkGet] has not been implemented. See GraphStorage class.`);
  }
  async create(ctx, data, options) {
    const {
      utils: {
        getTransforms
      },
      version: {
        request: requestVersion
      }
    } = ctx;
    const transforms = getTransforms(_cm_services.cmServicesDefinition, requestVersion);

    // Validate input (data & options) & UP transform them to the latest version
    const {
      value: dataToLatest,
      error: dataError
    } = transforms.create.in.data.up(data);
    if (dataError) {
      throw _boom.default.badRequest(`Invalid data. ${dataError.message}`);
    }
    const {
      value: optionsToLatest,
      error: optionsError
    } = transforms.create.in.options.up(options);
    if (optionsError) {
      throw _boom.default.badRequest(`Invalid options. ${optionsError.message}`);
    }

    // Save data in DB
    const soClient = await savedObjectClientFromRequest(ctx);
    const savedObject = await soClient.create(SO_TYPE, dataToLatest, optionsToLatest);

    // Validate DB response and DOWN transform to the request version
    const {
      value,
      error: resultError
    } = transforms.create.out.result.down({
      item: savedObjectToGraphSavedObject(savedObject, false)
    });
    if (resultError) {
      throw _boom.default.badRequest(`Invalid response. ${resultError.message}`);
    }
    return value;
  }
  async update(ctx, id, data, options) {
    const {
      utils: {
        getTransforms
      },
      version: {
        request: requestVersion
      }
    } = ctx;
    const transforms = getTransforms(_cm_services.cmServicesDefinition, requestVersion);

    // Validate input (data & options) & UP transform them to the latest version
    const {
      value: dataToLatest,
      error: dataError
    } = transforms.update.in.data.up(data);
    if (dataError) {
      throw _boom.default.badRequest(`Invalid data. ${dataError.message}`);
    }
    const {
      value: optionsToLatest,
      error: optionsError
    } = transforms.update.in.options.up(options);
    if (optionsError) {
      throw _boom.default.badRequest(`Invalid options. ${optionsError.message}`);
    }

    // Save data in DB
    const soClient = await savedObjectClientFromRequest(ctx);
    const partialSavedObject = await soClient.update(SO_TYPE, id, dataToLatest, optionsToLatest);

    // Validate DB response and DOWN transform to the request version
    const {
      value,
      error: resultError
    } = transforms.update.out.result.down({
      item: savedObjectToGraphSavedObject(partialSavedObject, true)
    });
    if (resultError) {
      throw _boom.default.badRequest(`Invalid response. ${resultError.message}`);
    }
    return value;
  }
  async delete(ctx, id) {
    const soClient = await savedObjectClientFromRequest(ctx);
    await soClient.delete(SO_TYPE, id);
    return {
      success: true
    };
  }
  async search(ctx, query, options = {}) {
    var _query$tags;
    const {
      utils: {
        getTransforms
      },
      version: {
        request: requestVersion
      }
    } = ctx;
    const transforms = getTransforms(_cm_services.cmServicesDefinition, requestVersion);
    const soClient = await savedObjectClientFromRequest(ctx);

    // Validate and UP transform the options
    const {
      value: optionsToLatest,
      error: optionsError
    } = transforms.search.in.options.up(options);
    if (optionsError) {
      throw _boom.default.badRequest(`Invalid payload. ${optionsError.message}`);
    }
    const {
      searchFields = ['title^3', 'description'],
      types = ['graph-workspace']
    } = optionsToLatest;
    const {
      included,
      excluded
    } = (_query$tags = query.tags) !== null && _query$tags !== void 0 ? _query$tags : {};
    const hasReference = included ? included.map(id => ({
      id,
      type: 'tag'
    })) : undefined;
    const hasNoReference = excluded ? excluded.map(id => ({
      id,
      type: 'tag'
    })) : undefined;
    const soQuery = {
      type: types,
      search: query.text,
      perPage: query.limit,
      page: query.cursor ? Number(query.cursor) : undefined,
      defaultSearchOperator: 'AND',
      searchFields,
      hasReference,
      hasNoReference
    };

    // Execute the query in the DB
    const response = await soClient.find(soQuery);

    // Validate the response and DOWN transform to the request version
    const {
      value,
      error: resultError
    } = transforms.search.out.result.down({
      hits: response.saved_objects.map(so => savedObjectToGraphSavedObject(so, false)),
      pagination: {
        total: response.total
      }
    });
    if (resultError) {
      throw _boom.default.badRequest(`Invalid response. ${resultError.message}`);
    }
    return value;
  }
}
exports.GraphStorage = GraphStorage;