package com.airlock.iam.flow.shared.domain.model.item;

import com.airlock.iam.base.api.domain.model.mapification.MapifiedValues;
import com.airlock.iam.base.domain.model.mapification.MapificationUtils;
import com.airlock.iam.base.domain.model.mapification.MapifiedValuesBuilder;
import com.airlock.iam.common.domain.service.mapification.Mapifier;
import com.airlock.iam.flow.shared.api.domain.model.item.info.UserDataItemInfo;
import com.airlock.iam.flow.shared.api.domain.model.item.info.UserDataItemInfoFactory;
import com.airlock.iam.flow.shared.api.domain.model.item.info.UserDataItemType;

public final class UserDataItemInfoMapificationUtil {
   private static final String NAME_KEY = "name";
   private static final String TYPE_KEY = "type";
   private static final String CURRENT_VALUE_KEY = "currentValue";
   private static final String REQUIRED_KEY = "required";
   private static final String VALIDATION_INFO_KEY = "validationInfo";
   private static final String ALLOWED_VALUES_KEY = "allowedValues";
   private static final String TYPE_IS_SENSITIVE_KEY = "sensitive";
   private static final String TYPE_ID_KEY = "id";
   private static final String INPUT_PURPOSE_KEY = "inputPurpose";

   public static <T> MapifiedValues mapifyUserDataItemInfo(UserDataItemInfo<T> info) {
      return MapifiedValuesBuilder.mapifiedValues()
         .put("name", info.getName())
         .putIfPresent("type", info.getType().map(UserDataItemInfoMapificationUtil::mapifyType))
         .putIfPresent("currentValue", info.getCurrentValue().map(Mapifier.getInstance()::mapify))
         .putIfPresent("required", info.getRequired())
         .putIfNotEmpty("validationInfo", MapificationUtils.mapifyCollection(info.getValidationInfos(), Mapifier.getInstance()::mapify))
         .putIfNotEmpty("allowedValues", info.getAllowedValues())
         .putIfPresent("inputPurpose", info.getInputPurpose())
         .build();
   }

   public static <T> UserDataItemInfo<T> demapifyUserDataItemInfo(MapifiedValues values) {
      return UserDataItemInfoFactory.restoreUserDataItemInfo(
         values.get("name"),
         values.demapifyOptional("type", UserDataItemInfoMapificationUtil::demapifyType),
         values.demapifyOptional("currentValue", Mapifier.getInstance()::demapify),
         values.getOptional("required"),
         values.demapifyList("validationInfo", Mapifier.getInstance()::demapify),
         values.getList("allowedValues"),
         values.getOptional("inputPurpose")
      );
   }

   private static MapifiedValues mapifyType(UserDataItemType type) {
      return type instanceof Enum<?> enumtype
         ? MapificationUtils.mapifyEnum(enumtype)
         : MapifiedValuesBuilder.mapifiedValues().put("id", type.getId()).put("sensitive", type.isSensitive()).build();
   }

   private static UserDataItemType demapifyType(final MapifiedValues values) {
      return values.containsKey("enumName") ? MapificationUtils.demapifyEnum(values) : new UserDataItemType() {
         @Override
         public String getId() {
            return values.get("id");
         }

         @Override
         public boolean isSensitive() {
            return values.<Boolean>get("sensitive");
         }
      };
   }

   private UserDataItemInfoMapificationUtil() {
   }
}
