/*******************************************************************************
 * 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.InputStream;
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.apache.commons.lang.math.NumberUtils;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.commons.FormatUtils;
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.StorageConsumer;
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", "History");

    @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> categories = getCategories();
        ZipOutputRepresentation zipRepresentation = new ZipOutputRepresentation(storageService, categories);
        Disposition disposition = new Disposition(Disposition.TYPE_ATTACHMENT);
        disposition.setFilename(FILE_NAME);
        zipRepresentation.setDisposition(disposition);
        setStatus(Status.SUCCESS_OK);
        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 = getQueryAttribute(ACTION_PARAM);
        Set<String> categories = getCategories();

        Set<String> accepted = new HashSet<String>();
        Set<String> rejected = new HashSet<String>();
        for (String category: CATEGORIES) {
            if (categories.contains(category)) {
                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 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;
        }
        boolean withHistory = accepted.contains("History"); //$NON-NLS-1$

        int countItems = 0;
        int countHistoryItems = 0;
        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;
                        }
                        String category = parts[0];
                        String name = parts[1];
                        if (name.endsWith(".xml")) { //$NON-NLS-1$
                            name = name.substring(0, name.length() - 4);
                        };
                        String[] nameParts = StringUtils.split(name, '_');
                        String key = nameParts[0];
                        long timestamp = NumberUtils.toLong(nameParts.length == 2 ? nameParts[1] : null, -1L);

                        // ensure that the category of the entry, i.e. the directory name,
                        // is in the set of accepted categories
                        if (accepted.contains(category)) {
                            if (timestamp < 0) {
                                try {
                                    storageService.write(category, key, zipStream);
                                    ++countItems;
                                } 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 if (withHistory) {
                                try {
                                    storageService.writeToArchive(category, key, timestamp, zipStream);
                                    ++countHistoryItems;
                                } catch (IOException e) {
                                    LOG.error(MessageFormat.format(
                                            "Failed to store history entry for timestamp {0} with key {1} and category {2} ({3})",
                                            FormatUtils.formatUTCWithMillis(timestamp), 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);
        }
        if (LOG.isInfoEnabled()) {
            LOG.info(MessageFormat.format("Restored {0} items and {1} history items", countItems, countHistoryItems));
        }

        // 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;
    }

    /**
     * Start with a result set that contains all entries from CATEGORIES,
     * except if there is an include list; in this case start with an empty
     * result set. Then first add all categories contained in the include list
     * and remove afterwards all entries contained in the exclude list.
     */
    private Set<String> getCategories() {
        Set<String> categories = new HashSet<String>(CATEGORIES);
        Set<String> include = CollectionUtils.asSet(StringUtils.split(getQueryAttribute(INCLUDE_PARAM),
                SearchQuery.PARAM_LIST_SEPARATOR));
        Set<String> exclude = CollectionUtils.asSet(StringUtils.split(getQueryAttribute(EXCLUDE_PARAM),
                SearchQuery.PARAM_LIST_SEPARATOR));
        if (!include.isEmpty()) {
            categories.removeAll(CATEGORIES);
        }
        categories.addAll(include);
        categories.removeAll(exclude);
        return 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> categories;
        private boolean withHistory;

        public ZipOutputRepresentation(StorageService storageService, Set<String> categories) {
            super(MediaType.APPLICATION_ZIP);
            this.storageService = storageService;
            this.categories = categories;
            this.withHistory = categories.contains("History"); //$NON-NLS-1$
        }

        @Override
        public void write(OutputStream out) throws IOException {
            ZipOutputStream zipStream = null;
            try {
                zipStream = new ZipOutputStream(new BufferedOutputStream(out));
                for (String category: CATEGORIES) {
                    if (categories.contains(category)) {
                        write(category, zipStream);
                    }
                }
                zipStream.flush();
            } finally {
                IOUtils.closeQuietly(zipStream);
            }
        }

        private void write(String category, ZipOutputStream target) throws IOException {
            List<String> keys = storageService.keys(category);
            for (String key: keys) {
                write(category, key, target);
                if (withHistory) {
                    writeHistory(category, key, target);
                }
            }
        }

        private void write(String category, String key, final ZipOutputStream target) throws IOException {
            String entryName = MessageFormat.format("{0}/{1}.xml", category, key); //$NON-NLS-1$
            write(entryName, storageService.read(category, key), target);
        }

        private void writeHistory(String category, String key, final ZipOutputStream target) throws IOException {
            storageService.readFromArchive(category, key, new StorageConsumer() {
                @Override
                public void consume(String category, String key, long lastModified, InputStream blob)
                        throws IOException {
                    String entryName = MessageFormat.format("{0}/{1}_{2}.xml", //$NON-NLS-1$
                            category, key, Long.toString(lastModified));
                    write(entryName, blob, target);
                }
            });
        }

        private void write(String entryName, InputStream blob, ZipOutputStream target) throws IOException {
            BufferedInputStream source = null;
            try {
                source = new BufferedInputStream(blob, BUFFER);
                ZipEntry entry = new ZipEntry(entryName);
                target.putNextEntry(entry);
                int count;
                byte data[] = new byte[BUFFER];
                while ((count = source.read(data, 0, BUFFER)) != -1) {
                    target.write(data, 0, count);
                }
            } finally {
                IOUtils.closeQuietly(source);
            }
        }
    }

}
