/*
 * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 *
 * 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 org.keycloak.subsystem.server.extension;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationDefinition;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;

/**
 * This operation provides a migration path from keycloak-server.json to
 * standalone.xml or domain.xml.
 *
 * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
 */
public class MigrateJsonOperation implements OperationStepHandler {
    public static final String OPERATION_NAME = "migrate-json";
    
    private static final String CONFIG_DIR = System.getProperty("jboss.server.config.dir");
    private static final Path DEFAULT_CONFIG_FILE = Paths.get(CONFIG_DIR, "keycloak-server.json");

    private static final AttributeDefinition FILE_ATTRIBUTE = SimpleAttributeDefinitionBuilder.create("file", ModelType.BYTES, true).build();
    public static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OPERATION_NAME, KeycloakExtension.getResourceDescriptionResolver())
            .setRuntimeOnly()
            .setReadOnly()
            .setReplyType(ModelType.STRING)
            .setParameters(FILE_ATTRIBUTE)
            .build();

    private String localConfig() throws IOException {
        if (Files.notExists(DEFAULT_CONFIG_FILE)) return null;
        return new String(Files.readAllBytes(DEFAULT_CONFIG_FILE));
    }
    
    private String readConfig(ModelNode operation) throws IOException {
        ModelNode file = operation.get(FILE_ATTRIBUTE.getName());
        if (file.isDefined() && file.asBytes().length > 0) {
            return new String(file.asBytes());
        }
        
        String localConfig = localConfig();
        if (localConfig != null) return localConfig;
        
        throw new IOException("Can not find json file to migrate");
    }
    
    @Override
    public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
        List<ModelNode> ops = null;
        try {
            PathAddress currentAddr = context.getCurrentAddress();
            ops = JsonConfigConverter.convertJsonConfig(readConfig(operation), currentAddr);
        } catch (IOException ioe) {
            throw new OperationFailedException(ioe);
        }
         
        for (ModelNode op : ops) {
            PathAddress addr = PathAddress.pathAddress(op.get(ADDRESS));
            String opName = op.get(OP).asString();
            context.addStep(op, 
                            context.getRootResourceRegistration().getOperationHandler(addr, opName), 
                            OperationContext.Stage.MODEL);
        }
        
        context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
    }
    
}
