package com.airlock.iam.admin.infrastructure.mapper.prot;

import ch.ergon.restal.jsonapi.document.data.Relationship;
import ch.ergon.restal.jsonapi.document.data.ResourceIdentifier;
import ch.ergon.restal.jsonapi.document.data.Relationship.ToManyRelationship;
import ch.ergon.restal.jsonapi.document.data.Relationship.ToOneRelationship;
import com.airlock.iam.admin.infrastructure.transfer.response.techclient.PlainTechClientData;
import com.airlock.iam.admin.infrastructure.transfer.response.techclient.PlainTechClientLockData;
import com.airlock.iam.base.api.domain.model.identity.Identity;
import com.airlock.iam.base.infrastructure.mapper.jsonapi.ResourceObjectMetaData;
import com.airlock.iam.common.api.domain.model.locking.LockInfo;
import com.airlock.iam.techclient.admin.domain.model.PlainTechClient;
import java.util.List;
import java.util.stream.Collectors;
import ma.glasnost.orika.CustomMapper;
import ma.glasnost.orika.DefaultFieldMapper;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;

public class PlainTechClientMapper {
   public PlainTechClientMapper(MapperFactory factory) {
      this.configure(factory);
   }

   private void configure(MapperFactory factory) {
      factory.classMap(PlainTechClient.class, PlainTechClientData.class)
         .field("lockInfo", "lock")
         .field("description:{getDescription}", "description")
         .field("label:{getLabel}", "label")
         .byDefault(new DefaultFieldMapper[0])
         .register();
      factory.classMap(PlainTechClient.class, ResourceObjectMetaData.class).customize(new PlainTechClientMapper.PlainTechClientCustomMapper()).register();
      factory.classMap(LockInfo.class, PlainTechClientLockData.class).field("lockReason", "reason").byDefault(new DefaultFieldMapper[0]).register();
   }

   private static final class PlainTechClientCustomMapper extends CustomMapper<PlainTechClient, ResourceObjectMetaData> {
      public void mapAtoB(PlainTechClient techClient, ResourceObjectMetaData metaData, MappingContext context) {
         metaData.withRelationship("subscription", getSubscriptionRelationship(techClient));
         metaData.withRelationship("api-keys", getAPIKeyRelationships(techClient));
      }

      private static Relationship getSubscriptionRelationship(PlainTechClient client) {
         ToOneRelationship relationshipItem = new ToOneRelationship();
         if (client.getSubscriptionId().isPresent()) {
            relationshipItem.setData(toResourceIdentifier(((Identity)client.getSubscriptionId().get()).asString(), "subscription"));
         }

         return relationshipItem;
      }

      private static Relationship getAPIKeyRelationships(PlainTechClient client) {
         ToManyRelationship relationshipItem = new ToManyRelationship();
         List<ResourceIdentifier> apiKeyRelationships = client.getApiKeyIds()
            .stream()
            .map(k -> toResourceIdentifier(k.asString(), "api-key"))
            .collect(Collectors.toList());
         relationshipItem.setData(apiKeyRelationships);
         return relationshipItem;
      }

      private static ResourceIdentifier toResourceIdentifier(String id, String type) {
         ResourceIdentifier identifier = new ResourceIdentifier();
         identifier.setType(type);
         identifier.setId(id);
         return identifier;
      }
   }
}
