/*******************************************************************************
 * Copyright (c) 2010-2014 SAP AG and others.
 * 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:
 *     SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.skalli.core.rest.admin;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.commons.ThreadPool;
import org.eclipse.skalli.core.storage.FileStorageComponent;
import org.eclipse.skalli.services.BundleProperties;
import org.eclipse.skalli.services.ServiceFilter;
import org.eclipse.skalli.services.Services;
import org.eclipse.skalli.services.extension.rest.ResourceBase;
import org.eclipse.skalli.services.permit.Permits;
import org.eclipse.skalli.services.persistence.PersistenceService;
import org.eclipse.skalli.services.persistence.StorageService;
import org.eclipse.skalli.services.search.SearchQuery;
import org.restlet.data.Disposition;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProjectBackupResource extends ResourceBase {

    private static final Logger LOG = LoggerFactory.getLogger(ProjectBackupResource.class);

    private static final String FILE_NAME = "backup.zip"; //$NON-NLS-1$

    private static final String EXCLUDE_PARAM = "exclude"; //$NON-NLS-1$
    private static final String INCLUDE_PARAM = "include"; //$NON-NLS-1$

    private static final String ACTION_PARAM = "action"; //$NON-NLS-1$
    private static final String ACTION_OVERWRITE = "overwrite"; //$NON-NLS-1$

    // error codes for logging and error responses
    private static final String ID_PREFIX = "rest:api/admin/backup:"; //$NON-NLS-1$
    private static final String ERROR_ID_IO_ERROR = ID_PREFIX + "00"; //$NON-NLS-1$
    private static final String ERROR_ID_NO_STORAGE_SERVICE = ID_PREFIX + "10"; //$NON-NLS-1$
    private static final String ERROR_ID_FAILED_TO_RETRIEVE_KEYS = ID_PREFIX + "20"; //$NON-NLS-1$
    private static final String ERROR_ID_FAILED_TO_STORE = ID_PREFIX + "30"; //$NON-NLS-1$
    private static final String ERROR_ID_OVERWRITE_EXISTING_DATA = ID_PREFIX + "40"; //$NON-NLS-1$

    @SuppressWarnings("nls")
    private static final Set<String> CATEGORIES = CollectionUtils.asSet("customization", "Project", "Issues",
            "Favorites", "User", "Group");

    @Get
    public Representation backup() {
        if (!Permits.isAllowed(getAction(), getPath())) {
            return createUnauthorizedRepresentation();
        }

        StorageService storageService = getStorageService();
        if (storageService == null) {
            return createServiceUnavailableRepresentation(ERROR_ID_NO_STORAGE_SERVICE, "Storage Service");
        }
        Set<String> included = getCategories(INCLUDE_PARAM);
        Set<String> excluded = getCategories(EXCLUDE_PARAM);
        ZipOutputRepresentation zipRepresentation = new ZipOutputRepresentation(storageService, included, excluded);
        Disposition disposition = new Disposition(Disposition.TYPE_ATTACHMENT);
        disposition.setFilename(FILE_NAME);
        zipRepresentation.setDisposition(disposition);
        return zipRepresentation;
    }

    @Put
    public Representation restore(Representation entity) {
        if (!Permits.isAllowed(getAction(), getPath())) {
            return createUnauthorizedRepresentation();
        }

        StorageService storageService = getStorageService();
        if (storageService == null) {
            return createServiceUnavailableRepresentation(ERROR_ID_NO_STORAGE_SERVICE, "Storage Service");
        }

        String action = getQuery().getValues(ACTION_PARAM);
        Set<String> included = getCategories(INCLUDE_PARAM);
        Set<String> excluded = getCategories(EXCLUDE_PARAM);

        Set<String> accepted = new HashSet<String>();
        Set<String> rejected = new HashSet<String>();
        for (String category: CATEGORIES) {
            if (included.size() > 0 && !included.contains(category)) {
                continue;
            }
            if (excluded.size() > 0 && excluded.contains(category)) {
                continue;
            }
            try {
                if (ACTION_OVERWRITE.equals(action) || storageService.keys(category).isEmpty()) {
                    accepted.add(category);
                } else {
                    rejected.add(category);
                }
            } catch (IOException e) {
                LOG.error(MessageFormat.format("Failed to retrieve keys for category {0} ({1})",
                        category, ERROR_ID_FAILED_TO_RETRIEVE_KEYS), e);
                return createErrorRepresentation(Status.SERVER_ERROR_INTERNAL, ERROR_ID_FAILED_TO_RETRIEVE_KEYS ,
                        "Failed to store the attached backup resource");
            }
        }
        if (rejected.size() > 0) {
            return createErrorRepresentation(
                    Status.CLIENT_ERROR_PRECONDITION_FAILED,
                    ERROR_ID_OVERWRITE_EXISTING_DATA,
                    MessageFormat.format(
                            "Restore might overwrite existing project data in the folling categories:\n{0}\n" +
                            "Either exclude these categories from the restore with a \"exclude=<comma-separated-list>\" " +
                            "parameter or enforce the restore with \"action=overwrite\".",
                             CollectionUtils.toString(rejected, '\n')));
        }
        if (accepted.isEmpty()) {
            setStatus(Status.SUCCESS_NO_CONTENT);
            return null;
        }

        ZipInputStream zipStream = null;
        try {
            zipStream = new ZipInputStream(entity.getStream());
            ZipEntry entry = zipStream.getNextEntry();
            while (entry != null) {
                try {
                    if (!entry.isDirectory()) {
                        String entryName = entry.getName().replace('\\', '/');
                        String[] parts = StringUtils.split(entryName, '/');
                        if (parts.length != 2) {
                            LOG.info(MessageFormat.format("Restore: {0} is not recognized as entity key", entryName));
                            continue;
                        }
                        // ensure that the category of the entry, i.e. the directory name,
                        // is in the set of accepted categories
                        String category = parts[0];
                        String key = parts[1];
                        if (accepted.contains(category)) {
                            if (key.endsWith(".xml")) { //$NON-NLS-1$
                                key = key.substring(0, key.length() - 4);
                            }
                            try {
                                storageService.write(category, key, zipStream);
                            } catch (IOException e) {
                                LOG.error(MessageFormat.format(
                                        "Failed to store entity with key {0} and category {1} ({2})",
                                        key, category, ERROR_ID_FAILED_TO_STORE), e);
                                return createErrorRepresentation(Status.SERVER_ERROR_INTERNAL, ERROR_ID_FAILED_TO_STORE,
                                        "Failed to store the attached backup");
                            }
                        } else {
                            LOG.info(MessageFormat.format("Restore: Excluded {0} (category ''{1}'' not accepted)",
                                    key, category));
                        }
                    }
                } finally {
                    zipStream.closeEntry();
                    entry = zipStream.getNextEntry();
                }
            }
        } catch (IOException e) {
            return createIOErrorRepresentation(ERROR_ID_IO_ERROR, e);
        } finally {
            IOUtils.closeQuietly(zipStream);
        }

        // ensure that the persistence service attached to the storage
        // refreshes all caches and reloads all entities --- do that
        // in the background, otherwise we might run into timeouts
        ThreadPool.submit(new Runnable() {
            @Override
            public void run() {
                PersistenceService persistenceService = Services.getService(PersistenceService.class);
                if (persistenceService != null) {
                    LOG.info("Refreshing all caches");
                    persistenceService.refreshAll();
                }
            }
        });

        setStatus(Status.SUCCESS_NO_CONTENT);
        return null;
    }

    private Set<String> getCategories(String paramId) {
        String[] categories = null;
        String ignoreAttribute = getQuery().getValues(paramId);
        if (ignoreAttribute != null) {
            categories = StringUtils.split(ignoreAttribute, SearchQuery.PARAM_LIST_SEPARATOR);
        }
        return CollectionUtils.asSet(categories);
    }

    private StorageService getStorageService() {
        final String storageServiceClassName = BundleProperties.getProperty(
                BundleProperties.PROPERTY_STORAGE_SERVICE, FileStorageComponent.class.getName());
        Set<StorageService> storageServices = Services.getServices(StorageService.class, new ServiceFilter<StorageService>() {
            @Override
            public boolean accept(StorageService instance) {
                return instance.getClass().getName().equals(storageServiceClassName);
            }
        });
        return storageServices.size() > 0? storageServices.iterator().next() : null;
    }

    private static class ZipOutputRepresentation extends OutputRepresentation {

        private static final int BUFFER = 2048;

        private StorageService storageService;
        private Set<String> included;
        private Set<String> excluded;

        public ZipOutputRepresentation(StorageService storageService, Set<String> included, Set<String> excluded) {
            super(MediaType.APPLICATION_ZIP);
            this.storageService = storageService;
            this.included = included;
            this.excluded = excluded;
        }

        @Override
        public void write(OutputStream paramOutputStream) throws IOException {
            ZipOutputStream out = null;
            try {
                out = new ZipOutputStream(new BufferedOutputStream(paramOutputStream));
                for (String category: CATEGORIES) {
                    // if there is an explicit include list, ensure that the
                    // category is contained in that list
                    if (included.size() > 0 && !included.contains(category)) {
                        continue;
                    }
                    // if there is an explicit exclude list, ensure that the
                    // category is not contained in that list
                    if (excluded.size() > 0 && excluded.contains(category)) {
                        continue;
                    }
                    write(category, out);
                }
            } finally {
                IOUtils.closeQuietly(out);
            }
        }

        private void write(String category, ZipOutputStream out) throws IOException {
            List<String> keys = storageService.keys(category);
            BufferedInputStream origin = null;
            for (String key: keys) {
                try {
                    origin = new BufferedInputStream(storageService.read(category, key), BUFFER);
                    ZipEntry entry = new ZipEntry(MessageFormat.format("{0}/{1}.xml", category, key)); //$NON-NLS-1$
                    out.putNextEntry(entry);
                    int count;
                    byte data[] = new byte[BUFFER];
                    while ((count = origin.read(data, 0, BUFFER)) != -1) {
                        out.write(data, 0, count);
                    }
                } finally {
                    IOUtils.closeQuietly(origin);
                }
            }
        }
    }

}
