/**
 * Copyright © CENRA (2016)
 *
 * remi.clement@espaces-naturels.fr
 * 
 * This software is a multi-platform and portable application based on 
 * the scientifical toolbox to monitor wetlands. With this toolbox it’s 
 * possible to calculate indicators «RhoMéO» to monitor quality, 
 * fonctionalities and urban and agricultural pressures of wetlands. 
 * Indicators are calculated using naturalist data entered and/or imported,
 * and geographic data downloaded from a geographic server.
 * 
 * This software is governed by the CeCILL license under French law and
 * abiding by the rules of distribution of free software.  You can  use, 
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info". 
 * 
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability. 
 * 
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or 
 * data to be ensured and,  more generally, to use and operate it in the 
 * same conditions as regards security. 
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
*/
package fr.cenra.rhomeo.core.state;

import fr.cenra.rhomeo.RhomeoTestCase;
import fr.cenra.rhomeo.api.data.Protocol;
import fr.cenra.rhomeo.api.data.Site;
import fr.cenra.rhomeo.api.data.TrackingPoint;
import fr.cenra.rhomeo.api.process.Indicator;
import fr.cenra.rhomeo.api.process.ProcessContext;
import fr.cenra.rhomeo.api.result.Index;
import fr.cenra.rhomeo.core.Session;
import fr.cenra.rhomeo.core.WorkflowStep;
import fr.cenra.rhomeo.core.data.MockIndicator;
import fr.cenra.rhomeo.core.data.MockProtocol;
import fr.cenra.rhomeo.core.data.MockStatement;
import fr.cenra.rhomeo.core.result.MockAnnualIndexSpi;
import fr.cenra.rhomeo.core.result.MockLocationIndexSpi;
import fr.cenra.rhomeo.core.data.site.DuplicatedKeyException;
import fr.cenra.rhomeo.core.data.site.SiteRepository;
import fr.cenra.rhomeo.core.data.site.SiteRepositoryImpl;
import fr.cenra.rhomeo.core.data.site.SiteRepositoryTest;
import static fr.cenra.rhomeo.core.data.site.SiteRepositoryTest.RESOURCES_DATA_SHP;
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.LocalDate;
import java.util.Collections;
import java.util.HashSet;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.DependsOnMethod;
import org.geotoolkit.data.FeatureReader;
import org.geotoolkit.data.query.QueryBuilder;
import org.geotoolkit.data.shapefile.ShapefileFeatureStore;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/**
 * TODO : activate back when the conflict with {@link SiteRepositoryTest} is
 * resolved.
 *
 * @author Alexis Manin (Geomatys)
 */
@DependsOn(SiteRepositoryTest.class)
public class StateManagementTest extends RhomeoTestCase {

    static final MockStatement STATEMENT = new MockStatement("toto", LocalDate.now());

    /*
     * STATE MANAGERS
     */

    @Autowired
    ProcessManager processManager;

    @Autowired
    ResultManager resultManager;

    /*
     * GLOBAL DATA
     */
    @Autowired
    StateManager manager;

    @Autowired
    SiteRepository repo;

    @Autowired
    Session session;

    @Autowired
    @Qualifier(MockProtocol.NAME)
    Protocol protocol;

    @Autowired
    @Qualifier(MockIndicator.NAME)
    Indicator indicator;

    @Autowired
    MockAnnualIndexSpi annualSpi;

    @Autowired
    MockLocationIndexSpi locationSpi;

    @Ignore
    @Test
    public void testSaveDataset() throws Exception {
        // Create a fake site for tests.
        final Site newSite = createMockSite(repo);

        // insert fake data
        session.startEdition(newSite, protocol);
        session.requestWorkflowStep(WorkflowStep.DATASET);

        session.getDataset().getItems().add(STATEMENT);
    }

    @Ignore
    @DependsOnMethod("testSaveDataset")
    @Test
    public void restoreDataset() throws Exception {
        manager.restoreState();

        // Restore data, check result
        Assert.assertTrue("Dataset has not been restored !", manager.restoreState());
        Assert.assertEquals("Dataset has not been filled !", 1, session.getDataset().getItems().size());
        Assert.assertEquals("Dataset does not contain the right statement !", StateManagementTest.STATEMENT, session.getDataset().getItems().get(0));
    }

    @Ignore
    @Test
    public void testProcess() throws Exception {
        final Site mSite = createMockSite(repo);
        session.startEdition(mSite, protocol);
        session.getDataset().getItems().addAll(
                new MockStatement("toto", LocalDate.now()),
                new MockStatement("toto", LocalDate.now().minusYears(1)),
                new MockStatement("tata", LocalDate.now().minusYears(1)),
                new MockStatement("titi", LocalDate.now().minusYears(4))
        );

        final ProcessContext pCtx = new ProcessContext(session.getDataset(), session.getDataContext());
        session.setProcessContext(pCtx);
        session.requestWorkflowStep(WorkflowStep.PROCESS);

        //pCtx.getTrackingPoints().addAll(session.getDataset().getTrackingPoints());
        pCtx.getIndicators().add(indicator);
        synchronized (this) {
            wait(200);
        }

        ProcessContext read = processManager.readProcessContext();
        Assert.assertNotNull("Backup process context", read);
        //Assert.assertTrue("Selected tracking points", read.getTrackingPoints().containsAll(session.getDataset().getTrackingPoints()));
        Assert.assertEquals(Collections.singleton(indicator), read.getIndicators());
    }

    @Ignore
    @Test
    public void testResults() throws Exception {
        final Site mSite = createMockSite(repo);
        session.startEdition(mSite, protocol);
        session.getDataset().getItems().addAll(
                new MockStatement("toto", LocalDate.now()),
                new MockStatement("titi", LocalDate.now().minusYears(4))
        );

        final ProcessContext pCtx = new ProcessContext(session.getDataset(), session.getDataContext());
        session.setProcessContext(pCtx);

        final HashSet<Index> results = new HashSet<>(4);
        final MockAnnualIndexSpi.MockAnnualIndex first = annualSpi.createIndex(10, 2016);
        final MockLocationIndexSpi.MockLocationIndex second = locationSpi.createIndex(4.3, (TrackingPoint) session.getDataset().getTrackingPoints().get(0));
        final MockAnnualIndexSpi.MockAnnualIndex third = annualSpi.createIndex(12, 2016);
        final MockLocationIndexSpi.MockLocationIndex fourth = locationSpi.createIndex(6d, (TrackingPoint) session.getDataset().getTrackingPoints().get(1));

        results.add(first);
        results.add(second);
        results.add(third);
        results.add(fourth);

        session.setResults(results);
        session.requestWorkflowStep(WorkflowStep.RESULT); // should start writing data
        synchronized (this) {
            wait(200);
        }

        session.setResults(null);
        Assert.assertTrue("Results should have been restored !", resultManager.restoreStep());

        Assert.assertEquals("Restored result", results, session.getResults());
    }

    static Site createMockSite(final SiteRepository repo) throws DataStoreException, IOException, DuplicatedKeyException, URISyntaxException {
        final Site newSite;
        try (final ShapefileFeatureStore testDataStore = new ShapefileFeatureStore(SiteRepositoryTest.class.getResource(RESOURCES_DATA_SHP).toURI(), "no namespace");
                final FeatureReader reader = testDataStore.getFeatureReader(QueryBuilder.all(testDataStore.getName()))) {

            newSite = SiteRepositoryImpl.toSite(reader.next());
            try {
                repo.create(newSite);
            } catch (DuplicatedKeyException e) {
                // The site already exists
            }
        }

        return newSite;
    }
}
