package org.apache.maven.continuum.management;

/*
 * 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.
 */

import org.apache.maven.continuum.model.project.v1_0_9.BuildDefinition;
import org.apache.maven.continuum.model.project.v1_0_9.BuildResult;
import org.apache.maven.continuum.model.project.v1_0_9.ContinuumDatabase;
import org.apache.maven.continuum.model.project.v1_0_9.Project;
import org.apache.maven.continuum.model.project.v1_0_9.ProjectDependency;
import org.apache.maven.continuum.model.project.v1_0_9.ProjectDeveloper;
import org.apache.maven.continuum.model.project.v1_0_9.ProjectGroup;
import org.apache.maven.continuum.model.project.v1_0_9.ProjectNotifier;
import org.apache.maven.continuum.model.project.v1_0_9.Schedule;
import org.apache.maven.continuum.model.project.v1_0_9.io.stax.ContinuumStaxReader;
import org.apache.maven.continuum.model.project.v1_0_9.io.stax.ContinuumStaxWriter;
import org.apache.maven.continuum.model.scm.v1_0_9.ChangeFile;
import org.apache.maven.continuum.model.scm.v1_0_9.ChangeSet;
import org.apache.maven.continuum.model.scm.v1_0_9.ScmResult;
import org.apache.maven.continuum.model.scm.v1_0_9.SuiteResult;
import org.apache.maven.continuum.model.scm.v1_0_9.TestCaseFailure;
import org.apache.maven.continuum.model.scm.v1_0_9.TestResult;
import org.apache.maven.continuum.model.system.v1_0_9.SystemConfiguration;
import org.apache.maven.continuum.store.ContinuumStoreException;
import org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory;
import org.codehaus.plexus.jdo.PlexusJdoUtils;
import org.codehaus.plexus.util.IOUtil;

import javax.jdo.FetchPlan;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * JDO implementation the database management tool API.
 *
 * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="legacy-continuum-jdo"
 */
public class LegacyJdoDataManagementTool
    implements DataManagementTool
{
    protected static final String BUILDS_XML = "builds.xml";

    /**
     * @plexus.requirement role="org.codehaus.plexus.jdo.JdoFactory" role-hint="continuum"
     */
    protected DefaultConfigurableJdoFactory factory;

    public void backupDatabase( File backupDirectory )
        throws IOException
    {
        PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdo109" );

        ContinuumDatabase database = new ContinuumDatabase();
        try
        {
            database.setSystemConfiguration( retrieveSystemConfiguration( pmf ) );
        }
        catch ( ContinuumStoreException e )
        {
            throw new DataManagementException( e );
        }

        Collection<ProjectGroup> projectGroups = retrieveAllProjectGroups( pmf );
        database.setProjectGroups( new ArrayList<ProjectGroup>( projectGroups ) );

        database.setSchedules( retrieveAllSchedules( pmf ) );

        ContinuumStaxWriter writer = new ContinuumStaxWriter();

        backupDirectory.mkdirs();
        OutputStream out = new FileOutputStream( new File( backupDirectory, BUILDS_XML ) );
        Writer fileWriter = new OutputStreamWriter( out, Charset.forName( database.getModelEncoding() ) );

        try
        {
            writer.write( fileWriter, database );
        }
        catch ( XMLStreamException e )
        {
            throw new DataManagementException( "Modello failure: unable to write data to StAX writer", e );
        }
        finally
        {
            IOUtil.close( fileWriter );
        }
    }

    private List retrieveAllSchedules( PersistenceManagerFactory pmf )
    {
        return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ), Schedule.class, "name ascending",
                                                     (String) null );
    }

    private Collection<ProjectGroup> retrieveAllProjectGroups( PersistenceManagerFactory pmf )
    {
        List<String> fetchGroups = Arrays.asList( "project-with-builds", "projectgroup-projects",
                                                  "build-result-with-details", "project-with-checkout-result",
                                                  "project-all-details", "project-build-details" );
        return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ), ProjectGroup.class, "name ascending",
                                                     fetchGroups );
    }

    private SystemConfiguration retrieveSystemConfiguration( PersistenceManagerFactory pmf )
        throws ContinuumStoreException
    {
        SystemConfiguration result;
        List systemConfs = PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ),
                                                                 SystemConfiguration.class, null, (String) null );

        if ( systemConfs == null || systemConfs.isEmpty() )
        {
            result = null;
        }
        else if ( systemConfs.size() > 1 )
        {
            throw new ContinuumStoreException(
                "Database is corrupted. There are more than one systemConfiguration object." );
        }
        else
        {
            result = (SystemConfiguration) systemConfs.get( 0 );
        }
        return result;
    }

    @SuppressWarnings({"OverlyCoupledMethod"})
    public void eraseDatabase()
    {
        PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdo109" );
        PersistenceManager persistenceManager = getPersistenceManager( pmf );
        PlexusJdoUtils.removeAll( persistenceManager, ProjectGroup.class );
        PlexusJdoUtils.removeAll( persistenceManager, Project.class );
        PlexusJdoUtils.removeAll( persistenceManager, Schedule.class );
        PlexusJdoUtils.removeAll( persistenceManager, ScmResult.class );
        PlexusJdoUtils.removeAll( persistenceManager, BuildResult.class );
        PlexusJdoUtils.removeAll( persistenceManager, TestResult.class );
        PlexusJdoUtils.removeAll( persistenceManager, SuiteResult.class );
        PlexusJdoUtils.removeAll( persistenceManager, TestCaseFailure.class );
        PlexusJdoUtils.removeAll( persistenceManager, SystemConfiguration.class );
        PlexusJdoUtils.removeAll( persistenceManager, ProjectNotifier.class );
        PlexusJdoUtils.removeAll( persistenceManager, ProjectDeveloper.class );
        PlexusJdoUtils.removeAll( persistenceManager, ProjectDependency.class );
        PlexusJdoUtils.removeAll( persistenceManager, ChangeSet.class );
        PlexusJdoUtils.removeAll( persistenceManager, ChangeFile.class );
        PlexusJdoUtils.removeAll( persistenceManager, BuildDefinition.class );
    }

    private PersistenceManager getPersistenceManager( PersistenceManagerFactory pmf )
    {
        PersistenceManager pm = pmf.getPersistenceManager();

        pm.getFetchPlan().setMaxFetchDepth( -1 );
        pm.getFetchPlan().setDetachmentOptions( FetchPlan.DETACH_LOAD_FIELDS );

        return pm;
    }

    public void restoreDatabase( File backupDirectory )
        throws IOException
    {
        ContinuumStaxReader reader = new ContinuumStaxReader();

        FileReader fileReader = new FileReader( new File( backupDirectory, BUILDS_XML ) );

        ContinuumDatabase database;
        try
        {
            database = reader.read( fileReader );
        }
        catch ( XMLStreamException e )
        {
            throw new DataManagementException( e );
        }
        finally
        {
            IOUtil.close( fileReader );
        }

        PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdorepl109" );

        PlexusJdoUtils.addObject( pmf.getPersistenceManager(), database.getSystemConfiguration() );

        Map<Integer, Schedule> schedules = new HashMap<Integer, Schedule>();
        for ( Iterator i = database.getSchedules().iterator(); i.hasNext(); )
        {
            Schedule schedule = (Schedule) i.next();

            schedule = (Schedule) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), schedule );
            schedules.put( Integer.valueOf( schedule.getId() ), schedule );
        }

        for ( Iterator i = database.getProjectGroups().iterator(); i.hasNext(); )
        {
            ProjectGroup projectGroup = (ProjectGroup) i.next();

            // first, we must map up any schedules, etc.
            processBuildDefinitions( projectGroup.getBuildDefinitions(), schedules );

            for ( Iterator j = projectGroup.getProjects().iterator(); j.hasNext(); )
            {
                Project project = (Project) j.next();

                processBuildDefinitions( project.getBuildDefinitions(), schedules );
            }

            PlexusJdoUtils.addObject( pmf.getPersistenceManager(), projectGroup );
        }
        pmf.close();
    }

    private PersistenceManagerFactory getPersistenceManagerFactory( String ext )
    {
        // Take control of the JDO instead of using the store, and configure a new persistence factory
        // that won't generate new object IDs.
        Properties properties = new Properties();
        //noinspection UseOfPropertiesAsHashtable
        properties.putAll( factory.getProperties() );
        properties.setProperty( "org.jpox.metadata.jdoFileExtension", ext );
        return JDOHelper.getPersistenceManagerFactory( properties );
    }

    private static void processBuildDefinitions( List buildDefinitions, Map<Integer, Schedule> schedules )
    {
        for ( Iterator i = buildDefinitions.iterator(); i.hasNext(); )
        {
            BuildDefinition def = (BuildDefinition) i.next();

            if ( def.getSchedule() != null )
            {
                def.setSchedule( schedules.get( Integer.valueOf( def.getSchedule().getId() ) ) );
            }
        }
    }
}
