/*******************************************************************************
 * Copyright (c) 2012-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/

package org.eclipse.che.api.workspace.server.stack;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;

import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.workspace.server.model.impl.stack.StackImpl;
import org.eclipse.che.api.workspace.server.spi.StackDao;
import org.eclipse.che.api.workspace.server.stack.image.StackIcon;
import org.eclipse.che.api.workspace.shared.stack.Stack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static java.lang.String.format;

/**
 * Class for loading list predefined {@link Stack} to the {@link StackDao}
 * and set {@link StackIcon} to the predefined stack.
 *
 * @author Alexander Andrienko
 */
@Singleton
public class StackLoader {
    private static final Logger LOG = LoggerFactory.getLogger(StackLoader.class);

    private static final Gson GSON = new GsonBuilder().create();

    private final Path     stackJsonPath;
    private final Path     stackIconFolderPath;
    private final StackDao stackDao;

    @Inject
    public StackLoader(@Named("che.stacks.default") String stacksPath,
                       @Named("che.stacks.images.storage") String stackIconFolder,
                       StackDao stackDao) {
        this.stackJsonPath = Paths.get(stacksPath);
        this.stackIconFolderPath = Paths.get(stackIconFolder);
        this.stackDao = stackDao;
    }

    /**
     * Load predefined stacks with their icons to the {@link StackDao}.
     */
    @PostConstruct
    public void start() {
        if (Files.exists(stackJsonPath) && Files.isRegularFile(stackJsonPath)) {
            try (BufferedReader reader = Files.newBufferedReader(stackJsonPath)) {
                List<StackImpl> stacks = GSON.fromJson(reader, new TypeToken<List<StackImpl>>() {}.getType());
                stacks.forEach(this::loadStack);
            } catch (Exception e) {
                LOG.error("Failed to store stacks ", e);
            }
        }
    }

    private void loadStack(StackImpl stack) {
        setIconData(stack, stackIconFolderPath);
        try {
            stackDao.update(stack);
        } catch (NotFoundException | ServerException e) {
            try {
                stackDao.create(stack);
            } catch (Exception ex) {
                LOG.error(format("Failed to load stack with id '%s' ", stack.getId()), ex.getMessage());
            }
        }
    }

    private void setIconData(StackImpl stack, Path stackIconFolderPath) {
        StackIcon stackIcon = stack.getStackIcon();
        if (stackIcon == null) {
            return;
        }
        try {
            Path stackIconPath = stackIconFolderPath.resolve(stackIcon.getName());
            if (Files.exists(stackIconPath) && Files.isRegularFile(stackIconPath)) {
                stackIcon = new StackIcon(stackIcon.getName(), stackIcon.getMediaType(), Files.readAllBytes(stackIconPath));
                stack.setStackIcon(stackIcon);
            } else {
                throw new IOException("Stack icon is not a file or doesn't exist by path: " + stackIconPath);
            }
        } catch (IOException e) {
            stack.setStackIcon(null);
            LOG.error(format("Failed to load stack icon data for the stack with id '%s'", stack.getId()), e);
        }
    }
}

@@ -1740,31 +1740,24 @@
     private 
-static 
 final Gson G
@@ -1763,37 +1763,8 @@
 GSON
- = new GsonBuilder().create()
 ;%0A%0A 
@@ -2248,16 +2248,245 @@
 tackDao;
+%0A%0A        //TODO remove this strategy after fix https://jira.codenvycorp.com/browse/CODENVY-651%0A        GSON = new GsonBuilder().setFieldNamingStrategy(field -%3E field.getName().equals(%22isDev%22) ? %22dev%22 : field.getName()).create();
 %0A    %7D%0A%0A

Fix mapping machine config for predefined stacks.