/* (non-Javadoc)
   * @see com.yukthi.webutils.controllers.IExtensionController#readExtensionField(java.lang.String, long)
   */
  @Override
  @ActionName(ACTION_TYPE_FETCH_FIELD)
  @ResponseBody
  @RequestMapping(
      value = "/read/{" + PARAM_NAME + "}/{" + PARAM_ID + "}",
      method = RequestMethod.GET)
  public ExtensionFieldReadResponse readExtensionField(
      @PathVariable(PARAM_NAME) String extensionName, @PathVariable(PARAM_ID) long fieldId) {
    logger.trace("Read field invoked with params [Extension: {}, Id: {}]", extensionName, fieldId);

    ExtensionEntityDetails extensionEntityDetails =
        extensionService.getExtensionEntityDetailsByName(extensionName);

    if (!securityService.isExtensionAuthorized(extensionEntityDetails)) {
      throw new UnauthorizedException(
          "Current user is not authorized to access extesion - {}", extensionName);
    }

    ExtensionFieldEntity fieldEntity = extensionService.fetchExtensionField(extensionName, fieldId);

    ExtensionFieldModel model = WebUtils.convertBean(fieldEntity, ExtensionFieldModel.class);
    model.setExtensionName(extensionName);

    return new ExtensionFieldReadResponse(model);
  }
  /* (non-Javadoc)
   * @see com.yukthi.webutils.controllers.IExtensionController#updateExtensionField(com.yukthi.webutils.common.models.ExtensionFieldModel)
   */
  @Override
  @ActionName(ACTION_TYPE_UPDATE)
  @ResponseBody
  @RequestMapping(value = "/update", method = RequestMethod.POST)
  public BaseResponse updateExtensionField(@RequestBody @Valid ExtensionFieldModel extensionField) {
    logger.trace("Update invoked with params [Field: {}]", extensionField);

    if (extensionField.getId() <= 0) {
      throw new InvalidRequestParameterException("Invalid/no extension field id specified.");
    }

    long extensionId =
        validateFieldForChange(extensionField.getExtensionName(), extensionField.getId());

    // validate specified model
    validateExtensionFieldForSave(extensionField);

    logger.debug("Updating extension field");
    ExtensionFieldEntity extFieldEntity =
        WebUtils.convertBean(extensionField, ExtensionFieldEntity.class);
    extFieldEntity.setExtension(new ExtensionEntity(extensionId));

    extensionService.updateExtensionField(extFieldEntity);

    return new BaseResponse("Success");
  }
  /* (non-Javadoc)
   * @see com.yukthi.webutils.controllers.IExtensionController#saveExtensionField(com.yukthi.webutils.common.models.ExtensionFieldModel)
   */
  @Override
  @ActionName(ACTION_TYPE_SAVE)
  @ResponseBody
  @RequestMapping(value = "/save", method = RequestMethod.POST)
  public BasicSaveResponse saveExtensionField(
      @RequestBody @Valid ExtensionFieldModel extensionField) {
    logger.trace("Save invoked with params [Field: {}]", extensionField);

    String extensionName = extensionField.getExtensionName();
    ExtensionEntityDetails extensionPointDetails =
        extensionService.getExtensionEntityDetailsByName(extensionName);

    if (extensionPointDetails == null) {
      throw new InvalidArgumentException("Invalid extension name specified - {}", extensionName);
    }

    if (!securityService.isExtensionAuthorized(extensionPointDetails)) {
      throw new UnauthorizedException(
          "Current user is not authorized to access extesion - {}", extensionName);
    }

    // fetch validate extension point name
    ExtensionEntity extensionEntity = extensionService.getExtensionEntity(extensionName);

    // validate specified model
    validateExtensionFieldForSave(extensionField);

    // if required extension does not exist, created one
    if (extensionEntity == null) {
      logger.debug(
          "No extension-entity found for extension '{}' with default owner. Trying to create new one",
          extensionName);
      ExtensionDetails extensionDetails =
          extensionContextProvider.getExtensionDetails(extensionName, extensionPointDetails);

      extensionEntity = new ExtensionEntity();
      extensionEntity.setName(extensionField.getExtensionName());

      if (extensionDetails.getOwnerType() != null) {
        extensionEntity.setOwnerEntityType(extensionDetails.getOwnerType().getName());
        extensionEntity.setOwnerEntityId(extensionDetails.getOwnerId());
      }

      extensionEntity.setAttributes(extensionDetails.getAttributes());
      extensionEntity.setTargetEntityType(extensionPointDetails.getEntityType().getName());

      extensionService.saveExtensionEntity(extensionEntity);
    }

    logger.debug("Saving extension field");
    ExtensionFieldEntity extFieldEntity =
        WebUtils.convertBean(extensionField, ExtensionFieldEntity.class);
    extensionService.saveExtensionField(extensionEntity.getId(), extFieldEntity);

    return new BasicSaveResponse(extFieldEntity.getId());
  }
  /**
   * Validates specified extension field model. Throws exception if validation fails.
   *
   * @param extensionField Extension field to validated.
   */
  private void validateExtensionFieldForSave(ExtensionFieldModel extensionField) {
    if (extensionField.getType() == ExtensionFieldType.LIST_OF_VALUES) {
      if (CollectionUtils.isEmpty(extensionField.getLovOptions())) {
        logger.error("No LOV options specified for lov field");
        throw new InvalidRequestParameterException("No LOV options specified for LOV field");
      }

      String lovOptStr =
          (String) jsonConverter.convertToDBType(extensionField.getLovOptions(), DataType.STRING);

      if (lovOptStr.length() > IWebUtilsInternalConstants.MAX_EXT_FIELD_LENGTH) {
        logger.error(
            "Too many or too long lov options specified. Got result json string length as - ",
            lovOptStr.length());
        throw new InvalidRequestParameterException("Too many or too long LOV options specified");
      }
    }

    // for string fields ensure proper length is specified
    if (extensionField.getType() == ExtensionFieldType.STRING
        || extensionField.getType() == ExtensionFieldType.MULTI_LINE_STRING) {
      if (extensionField.getMaxLength() <= 0
          || extensionField.getMaxLength() > IWebUtilsInternalConstants.MAX_EXT_FIELD_LENGTH) {
        logger.error(
            "Invalid length specified for string field. Length should be in the range of [1, {}]. Specified length - {}",
            IWebUtilsInternalConstants.MAX_EXT_FIELD_LENGTH,
            extensionField.getMaxLength());
        throw new InvalidRequestParameterException(
            "Invalid length specified for string field. Length should be in the range of [1, {}]. Specified length - {}",
            IWebUtilsInternalConstants.MAX_EXT_FIELD_LENGTH,
            extensionField.getMaxLength());
      }
    }
  }