/*
 * eXist-db Open Source Native XML Database
 * Copyright (C) 2001 The eXist-db Authors
 *
 * info@exist-db.org
 * http://www.exist-db.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package org.exist.webdav;

import com.bradmcevoy.http.exceptions.BadRequestException;
import com.bradmcevoy.http.exceptions.ConflictException;
import com.bradmcevoy.http.exceptions.NotAuthorizedException;
import com.bradmcevoy.http.exceptions.NotFoundException;
import com.ettrema.httpclient.*;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.protocol.HttpContext;
import org.exist.TestUtils;
import org.exist.test.ExistWebServer;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;

/**
 * Tests for copying a document via WebDAV.
 */
public class CopyTest {

    @ClassRule
    public static final ExistWebServer existWebServer = new ExistWebServer(true, false, true, true);

    @ClassRule
    public static final TemporaryFolder tempFolder = new TemporaryFolder();

    @Test
    public void copyXmlDocument() throws IOException, NotAuthorizedException, BadRequestException, HttpException, ConflictException, NotFoundException {
        final String srcDocName = "webdav-copy-test.xml";
        final String srcDocContent = "<elem1>Hello there</elem1>";
        final String destDocName = "webdav-copied-test.xml";
        copyDocument(srcDocName, srcDocContent, destDocName, "application/xml");
    }

    @Test
    public void copyBinDocument() throws IOException, NotAuthorizedException, BadRequestException, HttpException, ConflictException, NotFoundException {
        final String srcDocName = "webdav-copy-test.bin";
        final String srcDocContent = "0123456789";
        final String destDocName = "webdav-copied-test.bin";
        copyDocument(srcDocName, srcDocContent, destDocName, "application/octet-stream");
    }

    private void copyDocument(final String srcDocName, final String srcDocContent, final String destDocName, final String expectedMediaType) throws BadRequestException, HttpException, IOException, NotAuthorizedException, ConflictException, NotFoundException {
        final HostBuilder builder = new HostBuilder();
        builder.setServer("localhost");
        final int port = existWebServer.getPort();
        builder.setPort(port);
        builder.setRootPath("webdav/db");
        final Host host = builder.buildHost();

        // workaround pre-emptive auth issues of Milton Client
        final AbstractHttpClient httpClient = (AbstractHttpClient)host.getClient();
        httpClient.addRequestInterceptor(new AlwaysBasicPreAuth(TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD));

        final Folder folder = host.getFolder("/");
        assertNotNull(folder);

        // store document
        final byte data[] = srcDocContent.getBytes(UTF_8);
        final java.io.File tmpStoreFile = tempFolder.newFile();
        Files.write(tmpStoreFile.toPath(), data);
        assertNotNull(folder.uploadFile(srcDocName, tmpStoreFile, null));

        // retrieve document
        final com.ettrema.httpclient.Resource srcResource = folder.child(srcDocName);
        assertNotNull(srcResource);
        assertTrue(srcResource instanceof File);
        assertEquals(expectedMediaType, ((File) srcResource).contentType);
        final java.io.File tempRetrievedSrcFile = tempFolder.newFile();
        srcResource.downloadTo(tempRetrievedSrcFile, null);
        assertEquals(srcDocContent, new String(Files.readAllBytes(tempRetrievedSrcFile.toPath()), UTF_8));

        // copy document
        srcResource.copyTo(folder, destDocName);

        // retrieve copied document
        final com.ettrema.httpclient.Resource destResource = folder.child(destDocName);
        assertNotNull(destResource);
        assertTrue(destResource instanceof File);
        assertEquals(expectedMediaType, ((File) destResource).contentType);
        final java.io.File tempRetrievedDestFile = tempFolder.newFile();
        destResource.downloadTo(tempRetrievedDestFile, null);
        assertEquals(srcDocContent, new String(Files.readAllBytes(tempRetrievedDestFile.toPath()), UTF_8));
    }

    private static class AlwaysBasicPreAuth implements HttpRequestInterceptor {
        private final String username;
        private final String password;

        public AlwaysBasicPreAuth(final String username, final String password) {
            this.username = username;
            this.password = password;
        }

        @Override
        public void process(final HttpRequest request, final HttpContext context) {
            String token = Base64.getEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8));
            request.addHeader("Authorization", "Basic " + token);
        }
    }

}

Test for copying files via WebDAV