/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.maven.index.updater;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.TimeZone;

import org.apache.maven.index.Java11HttpClient;
import org.apache.maven.index.context.IndexingContext;
import org.codehaus.plexus.util.FileUtils;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class DownloadRemoteIndexerManagerTest extends AbstractIndexUpdaterTest {
    private Server server;

    private File fakeCentral;

    private IndexingContext centralContext;

    @Override
    public void setUp() throws Exception {
        super.setUp();

        fakeCentral = new File(getBasedir(), "target/repos/fake-central");
        fakeCentral.mkdirs();

        // create proxy server
        ServerSocket s = new ServerSocket(0);
        int port = s.getLocalPort();
        s.close();

        server = new Server(port);

        ResourceHandler resource_handler = new ResourceHandler();
        resource_handler.setResourceBase(fakeCentral.getAbsolutePath());
        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[] {resource_handler, new DefaultHandler()});
        server.setHandler(handlers);

        server.start();

        // make context "fake central"
        centralContext = indexer.addIndexingContext(
                "central",
                "central",
                fakeCentral,
                getDirectory("central"),
                "http://localhost:" + port,
                null,
                MIN_CREATORS);
    }

    @Override
    public void tearDown() throws Exception {
        server.stop();

        FileUtils.forceDelete(fakeCentral);

        super.tearDown();
    }

    @Test
    public void testRepoReindex() throws Exception {
        IndexUpdateRequest iur;

        File index1 = new File(getBasedir(), "src/test/resources/repo-index/index");
        File index2 = new File(getBasedir(), "src/test/resources/repo-index/index2");
        File centralIndex = new File(fakeCentral, ".index");

        // copy index 02
        overwriteIndex(index2, centralIndex);

        iur = new IndexUpdateRequest(centralContext, new Java11HttpClient());
        iur.setForceFullUpdate(true);

        updater.fetchAndUpdateIndex(iur);

        searchFor("org.sonatype.nexus", 8, centralContext);

        // copy index 01
        overwriteIndex(index1, centralIndex);

        iur = new IndexUpdateRequest(centralContext, new Java11HttpClient());
        iur.setForceFullUpdate(true);
        // just a dummy filter to invoke filtering! -- this is what I broke unnoticing it
        iur.setDocumentFilter(doc -> true);

        updater.fetchAndUpdateIndex(iur);

        searchFor("org.sonatype.nexus", 1, centralContext);

        // copy index 02
        overwriteIndex(index2, centralIndex);

        iur = new IndexUpdateRequest(centralContext, new Java11HttpClient());
        iur.setForceFullUpdate(true);

        updater.fetchAndUpdateIndex(iur);

        searchFor("org.sonatype.nexus", 8, centralContext);
    }

    private void overwriteIndex(File source, File destination) throws Exception {
        File indexFile = new File(destination, "nexus-maven-repository-index.gz");
        File indexProperties = new File(destination, "nexus-maven-repository-index.properties");

        long lastMod = -1;
        if (destination.exists()) {
            FileUtils.forceDelete(destination);
            lastMod = indexFile.lastModified();
        }
        FileUtils.copyDirectory(source, destination);
        long lastMod2 = indexFile.lastModified();
        assertTrue(lastMod < lastMod2);

        Properties p = new Properties();
        try (InputStream input = Files.newInputStream(indexProperties.toPath())) {
            p.load(input);
        }

        p.setProperty("nexus.index.time", format(new Date()));
        p.setProperty("nexus.index.timestamp", format(new Date()));

        try (OutputStream output = Files.newOutputStream(indexProperties.toPath())) {
            p.store(output, null);
        }
    }

    private String format(Date d) {
        SimpleDateFormat df = new SimpleDateFormat(IndexingContext.INDEX_TIME_FORMAT);
        df.setTimeZone(TimeZone.getTimeZone("GMT"));
        return df.format(d);
    }
}
