/*
 * Copyright 2017 The Mifos Initiative.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.mifos.provisioner.internal.service.applications;


import io.mifos.anubis.api.v1.client.Anubis;
import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
import io.mifos.anubis.api.v1.domain.PermittableEndpoint;
import io.mifos.identity.api.v1.client.IdentityManager;
import io.mifos.identity.api.v1.client.PermittableGroupAlreadyExistsException;
import io.mifos.identity.api.v1.client.TenantAlreadyInitializedException;
import io.mifos.identity.api.v1.domain.PermittableGroup;
import io.mifos.provisioner.config.ProvisionerConstants;
import io.mifos.tool.crypto.HashGenerator;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Myrle Krantz
 */
@Component
public class IdentityServiceInitializer {

  private final ApplicationCallContextProvider applicationCallContextProvider;
  private final HashGenerator hashGenerator;
  private final Logger logger;

  @Value("${system.domain}")
  private String domain;

  public class IdentityServiceInitializationResult {
    private final ApplicationSignatureSet signatureSet;
    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    private final Optional<String> adminPassword;

    private IdentityServiceInitializationResult(final ApplicationSignatureSet signatureSet, final String adminPassword) {
      this.signatureSet = signatureSet;
      this.adminPassword = Optional.of(adminPassword);
    }

    private IdentityServiceInitializationResult(final ApplicationSignatureSet signatureSet) {
      this.signatureSet = signatureSet;
      this.adminPassword = Optional.empty();
    }

    public ApplicationSignatureSet getSignatureSet() {
      return signatureSet;
    }

    public Optional<String> getAdminPassword() {
      return adminPassword;
    }
  }

  @Autowired
  public IdentityServiceInitializer(
          final ApplicationCallContextProvider applicationCallContextProvider,
          final HashGenerator hashGenerator,
          @Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger) {
    this.applicationCallContextProvider = applicationCallContextProvider;
    this.hashGenerator = hashGenerator;
    this.logger = logger;
  }

  public IdentityServiceInitializationResult initializeIsis(
          final @Nonnull String tenantIdentifier,
          final @Nonnull String applicationName,
          final @Nonnull String identityManagerUri) {
    try (final AutoCloseable ignored
                 = applicationCallContextProvider.getApplicationCallContext(tenantIdentifier, applicationName))
    {
      final IdentityManager identityService = applicationCallContextProvider.getApplication(IdentityManager.class, identityManagerUri);
      try {
        final String randomPassword = RandomStringUtils.random(8, true, true);

        final byte[] salt = Base64Utils.encode(("antony" + tenantIdentifier + this.domain).getBytes());

        final String encodedPassword = Base64Utils.encodeToString(randomPassword.getBytes());

        final byte[] hash = this.hashGenerator.hash(encodedPassword, salt, ProvisionerConstants.ITERATION_COUNT, ProvisionerConstants.HASH_LENGTH);
        final String encodedPasswordHash = Base64Utils.encodeToString(hash);

        final ApplicationSignatureSet signatureSet = identityService.initialize(encodedPasswordHash);
        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' succeeded with signature set '{}'.", tenantIdentifier, signatureSet);

        return new IdentityServiceInitializationResult(signatureSet, encodedPasswordHash);
      } catch (final TenantAlreadyInitializedException aiex) {
        final Anubis identityManagerAnubisApi = applicationCallContextProvider.getApplication(Anubis.class, identityManagerUri);
        final ApplicationSignatureSet signatureSet = identityManagerAnubisApi.getLatestSignatureSet();
        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' failed because it was already initialized.  Pre-existing signature set '{}'.",
                tenantIdentifier, signatureSet);

        return new IdentityServiceInitializationResult(signatureSet);
      }
    } catch (final Exception e) {
      throw new IllegalStateException(e);
    }
  }

  public void postPermittableGroups(
          final @Nonnull String tenantIdentifier,
          final @Nonnull String identityManagerApplicationName,
          final @Nonnull String identityManagerApplicationUri,
          final @Nonnull String applicationUri)
  {
    final List<PermittableEndpoint> permittables;
    try (final AutoCloseable ignored = applicationCallContextProvider.getApplicationCallGuestContext(tenantIdentifier)) {
      permittables = getPermittables(applicationUri);
    } catch (final Exception e) {
      throw new IllegalStateException(e);
    }

    try (final AutoCloseable ignored
                 = applicationCallContextProvider.getApplicationCallContext(tenantIdentifier, identityManagerApplicationName))
    {
      final IdentityManager identityService = applicationCallContextProvider.getApplication(IdentityManager.class, identityManagerApplicationUri);

      final List<PermittableGroup> permittableGroups = getPermittableGroups(permittables);

      permittableGroups.forEach(x -> createOrFindPermittableGroup(identityService, x));
    } catch (final Exception e) {
      throw new IllegalStateException(e);
    }
  }

  List<PermittableEndpoint> getPermittables(final @Nonnull String applicationUri)
  {
    try {
      final Anubis anubis = this.applicationCallContextProvider.getApplication(Anubis.class, applicationUri);
      return anubis.getPermittableEndpoints();
    }
    catch (final RuntimeException unexpected)
    {
      logger.error("Request for permittable endpoints to '{}' failed.", applicationUri, unexpected);
      return Collections.emptyList();
    }
  }

  static List<PermittableGroup> getPermittableGroups(final @Nonnull List<PermittableEndpoint> permittables)
  {
    final Map<String, Set<PermittableEndpoint>> groupedPermittables = new HashMap<>();

    permittables.forEach(x -> groupedPermittables.computeIfAbsent(x.getGroupId(), y -> new LinkedHashSet<>()).add(x));

    return groupedPermittables.entrySet().stream()
            .map(entry -> new PermittableGroup(entry.getKey(), entry.getValue().stream().collect(Collectors.toList())))
            .collect(Collectors.toList());
  }

  void createOrFindPermittableGroup(
          final @Nonnull IdentityManager identityService,
          final @Nonnull PermittableGroup permittableGroup) {
    try {
      identityService.createPermittableGroup(permittableGroup);
      logger.info("Group '{}' successfully created in identity service.", permittableGroup.getIdentifier());
    }
    catch (final PermittableGroupAlreadyExistsException groupAlreadyExistsException)
    {
      //if the group already exists, read out and compare.  If the group is the same, there is nothing left to do.
      final PermittableGroup existingGroup = identityService.getPermittableGroup(permittableGroup.getIdentifier());
      if (!existingGroup.getIdentifier().equals(permittableGroup.getIdentifier())) {
        logger.error("Group '{}' already exists, but has a different name{} (strange).", permittableGroup.getIdentifier(), existingGroup.getIdentifier());
      }

      //Compare as sets because I'm not going to get into a hissy fit over order.
      final Set<PermittableEndpoint> existingGroupPermittables = new HashSet<>(existingGroup.getPermittables());
      final Set<PermittableEndpoint> newGroupPermittables = new HashSet<>(permittableGroup.getPermittables());
      if (!existingGroupPermittables.equals(newGroupPermittables)) {
        logger.error("Group '{}' already exists, but has different contents.", permittableGroup.getIdentifier());
      }
    }
    catch (final RuntimeException unexpected)
    {
      logger.error("Creating group '{}' failed.", permittableGroup.getIdentifier(), unexpected);
    }
  }
}
