/*
 * 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.openjpa.persistence.graph;

import java.sql.Date;
import java.util.Arrays;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.FieldStrategy;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.meta.ValueHandler;
import org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.HandlerHandlerMapTableFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.UntypedPCValueHandler;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;

/**
 * Tests basic create and query on generic persistent graph. The test creates a
 * graph of People and Cities. Then different queries on the graph are verified.
 *
 * @author Pinaki Poddar
 *
 */
public class TestPersistentGraph extends SingleEMFTestCase {
    private static enum Emotion {
        LOVES, HATES, KNOWS
    }

    // Identity of People is their SSN
    private static final long[] SSN = { 123456781, 123456782, 123456783, 123456784, 123456785 };
    private static final String[] PERSON_NAMES = { "P1", "P2", "P3", "P4", "P5" };
    private static final String[] CITY_NAMES = { "San Francisco", "Paris", "Rome" };

    private static final String ATTR_SINCE = "since";
    private static final Date SINCE = new Date(90, 1, 27);

    private static final String ATTR_EMOTION = "feels";
    private static final Emotion[][] EMOTIONS = {
                            /*    P1             P2             P3             P4             P5       */
    /* P1 */new Emotion[] {          null, Emotion.LOVES, Emotion.HATES,          null, Emotion.KNOWS },
    /* P2 */new Emotion[] { Emotion.LOVES,          null, Emotion.LOVES,          null, Emotion.LOVES },
    /* P3 */new Emotion[] { Emotion.HATES, Emotion.LOVES,          null,          null, Emotion.KNOWS },
    /* P4 */new Emotion[] { Emotion.LOVES, Emotion.HATES, Emotion.KNOWS, Emotion.LOVES, Emotion.LOVES },
    /* P5 */new Emotion[] {          null, Emotion.LOVES, Emotion.KNOWS, Emotion.KNOWS,          null },
    };

    private static final String ATTR_DISTANCE = "distance";
    private static final int[][] ATTR_DISTANCE_VALUE = {
                       /* C1 C2 C3 */
    /* C1 */new int[] { 0, 200, 400 },
    /* C2 */new int[] { 200, 0, 500 },
    /* C3 */new int[] { 400, 500, 0 }
    };

    private EntityManager em;
    private PersistentGraph<Object> graph;

    @Override
    public void setUp() throws Exception {
        super.setUp(CLEAR_TABLES, PersistentGraph.class, RelationGraph.class,
                PersistentRelation.class, People.class, City.class);
        em = emf.createEntityManager();
        graph = createData();
        em.clear();
    }

    /**
     * Verifies that fields are mapped with expected strategy or value handlers.
     */
    public void testMapping() {
        assertStrategy(PersistentRelation.class, "source", HandlerFieldStrategy.class, UntypedPCValueHandler.class);
        assertStrategy(PersistentRelation.class, "target", HandlerFieldStrategy.class, UntypedPCValueHandler.class);
        assertStrategy(PersistentRelation.class, "attrs", HandlerHandlerMapTableFieldStrategy.class, null);
    }

    private void printMapping(FieldMapping fm) {
        System.err.println("Field :" + fm.getName());
        System.err.println("Type :" + fm.getTypeCode() + " " + fm.getType());
        System.err.println("Type (declared):" + fm.getDeclaredTypeCode() + " " + fm.getDeclaredType());
        System.err.println("Type Override :" + fm.getTypeOverride());
        System.err.println("Key type  :" + fm.getKey().getType());
        System.err.println("Key declared type  :" + fm.getKey().getDeclaredType());
        System.err.println("Element type  :" + fm.getElement().getType());
        System.err.println("Element declared type  :" + fm.getElement().getDeclaredType());
    }

    FieldMapping getFieldMapping(Class<?> pcClass, String field) {
        MappingRepository repos = (MappingRepository) emf.getConfiguration()
                .getMetaDataRepositoryInstance();
        ClassMapping cmd = repos.getMapping(pcClass, null, true);
        assertNotNull("No metadata found for " + pcClass, cmd);
        FieldMapping fmd = cmd.getFieldMapping(field);
        assertNotNull("No metadata found for " + pcClass.getName() + "." + field + " Fields are "
                + Arrays.toString(cmd.getFieldNames()), fmd);
        return fmd;
    }

    /**
     * Asserts that the given field of the given class has been mapped with the
     * given strategy or value handler.
     */
    void assertStrategy(Class<?> pcClass, String field, Class<? extends FieldStrategy> strategy,
            Class<? extends ValueHandler> handler) {

        FieldMapping fmd = getFieldMapping(pcClass, field);
        FieldStrategy actualStrategy = ((FieldMapping) fmd).getStrategy();
        assertEquals(strategy, actualStrategy.getClass());
        ValueHandler actualHandler = fmd.getHandler();
        if (handler == null) {
            if (actualHandler != null) {
                printMapping(fmd);
                fail("Expected no value handler for " + pcClass.getName() + "." + field +
                        " but found " + actualHandler);
            }
        } else {
            if (actualHandler == null) {
                printMapping(fmd);
                fail("Expected a value handler for " + pcClass.getName() + "." + field + " but found null");
            }
            if (!handler.equals(actualHandler.getClass())) {
                printMapping(fmd);
                assertEquals(handler, fmd.getHandler().getClass());
            }
        }
    }

    FieldStrategy getStrategy(Class<?> cls, String field) {
        MetaDataRepository repos = emf.getConfiguration().getMetaDataRepositoryInstance();
        ClassMetaData cmd = repos.getMetaData(cls, null, true);
        assertNotNull("No metadat found for " + cls, cmd);
        FieldMetaData fmd = cmd.getField(field);
        assertNotNull("No metadata found for " + cls.getName() + "." + field + " Fields are "
                + Arrays.toString(cmd.getFieldNames()), fmd);
        FieldStrategy strategy = ((FieldMapping) fmd).getStrategy();
        System.err.println(cls.getName() + "." + field + ":" + strategy.getClass().getSimpleName());
        return strategy;
    }

    /**
     * Tests that the nodes retrieved from the database meets the same
     * assertions of the created graph.
     */
    public void testCreateGraph() {
        em.getTransaction().begin();
        assertFalse(em.contains(graph));
        graph = em.find(PersistentGraph.class, graph.getId());
        assertNotNull(graph);
        People[] people = new People[SSN.length];
        for (int i = 0; i < SSN.length; i++) {
            People p = em.find(People.class, SSN[i]);
            assertNotNull(p);
            people[i] = p;
        }
        City[] cities = new City[CITY_NAMES.length];
        for (int i = 0; i < CITY_NAMES.length; i++) {
            City c = em.find(City.class, CITY_NAMES[i]);
            assertNotNull(c);
            cities[i] = c;
        }
        assertDataEquals(graph, people, cities);

        em.getTransaction().rollback();
    }

    /**
     * Tests that relation can be queried and their references are set
     * correctly.
     */
    public void testQueryRelation() {
        String jpql = "select r from PersistentRelation r";
        List<PersistentRelation> relations = em.createQuery(jpql, PersistentRelation.class).getResultList();
        for (Relation<?, ?> r : relations) {
            Object source = r.getSource();
            Object target = r.getTarget();
            if (source instanceof People) {
                int i = indexOf((People) source);
                if (target instanceof People) {
                    int j = indexOf((People) target);
                    assertNotNull(EMOTIONS[i][j]);
                    assertEquals(EMOTIONS[i][j].toString(), r.getAttribute(ATTR_EMOTION));
                } else if (target instanceof City) {
                    int j = indexOf((City) target);
                    assertEquals(i % CITY_NAMES.length, j);
                    assertTrue(r.getAttributes().isEmpty());
                } else if (target != null){
                    fail("Unexpected relation " + r);
                }
            } else if (source instanceof City) {
                int i = indexOf((City) source);
                if (target instanceof City) {
                    int j = indexOf((City) target);
                    assertEquals(""+ATTR_DISTANCE_VALUE[i][j], r.getAttribute(ATTR_DISTANCE));
                } else if (target != null) {
                    fail("Unexpected relation " + r);
                }
            }
        }
    }

    /**
     * Tests that a relation can be queried predicated on its source vertex.
     */
    public void testQueryRelationOnSourceParameter() {
        People p1 = em.find(People.class, SSN[0]);
        String jpql = "select r from PersistentRelation r where r.source = :node";
        List<PersistentRelation> result = em.createQuery(jpql, PersistentRelation.class)
                                  .setParameter("node", p1)
                                  .getResultList();
        assertFalse("Result of [" + jpql + "] on source = " + p1 + " should not be empty", result.isEmpty());
    }

    /**
     * Tests that a relation can be queried predicated on its attribute key.
     */
    public void testQueryRelationOnSingleAttributeKey() {
        String jpql = "select r from PersistentRelation r join r.attrs a where key(a) = :key";
        List<PersistentRelation> result = em.createQuery(jpql, PersistentRelation.class)
                                  .setParameter("key", ATTR_EMOTION)
                                  .getResultList();

        assertFalse("Result of [" + jpql + "] on key = " + ATTR_EMOTION + " should not be empty", result.isEmpty());
    }

    /**
     * Tests that a relation can be queried predicated on a single attribute
     * key-value pair.
     */
    public void testQueryRelationOnSingleAttributeKeyValue() {
        String jpql = "select r from PersistentRelation r join r.attrs a where key(a) = :key and value(a) = :value";
        String value = EMOTIONS[0][2].toString();
        List<PersistentRelation> result = em.createQuery(jpql, PersistentRelation.class)
                                  .setParameter("key", ATTR_EMOTION)
                                  .setParameter("value", value)
                                  .getResultList();

        assertFalse("Result of [" + jpql + "] on key-value (" + ATTR_EMOTION + "," + value + ") should not be empty",
                result.isEmpty());
    }

    /**
     * Tests that a relation can be queried predicated on a multiple attribute
     * key-value pair. This requires multiple joins. Single join will produce
     * wrong result.
     */
    public void testQueryRelationOnMultipleAttributeKeyValuePairs() {
        String jpql = "select r from PersistentRelation r join r.attrs a1 join r.attrs a2 "
                    + "where key(a1) = :key1 and value(a1) = :value1 "
                    + "and key(a2) = :key2 and value(a2) = :value2";
        String value = EMOTIONS[0][2].toString();
        List<PersistentRelation> result = em.createQuery(jpql, PersistentRelation.class)
                                  .setParameter("key1", ATTR_EMOTION)
                                  .setParameter("value1", value)
                                  .setParameter("key2", ATTR_SINCE)
                                  .setParameter("value2", SINCE.toString())
                                  .getResultList();

        assertFalse("Result of [" + jpql + "] on key-value = (" + ATTR_EMOTION + "," + value
                + ") and key-value=("  + ATTR_SINCE + "," + SINCE + ") should not be empty",
                result.isEmpty());

        String wrongJPQL = "select r from PersistentRelation r join r.attrs a "
                         + "where key(a) = :key1 and value(a) = :value1 "
                         + "and key(a) = :key2 and value(a) = :value2";
        List<PersistentRelation> result2 = em.createQuery(wrongJPQL, PersistentRelation.class)
                                   .setParameter("key1", ATTR_EMOTION)
                                   .setParameter("value1", value)
                                   .setParameter("key2", ATTR_SINCE)
                                   .setParameter("value2", SINCE.toString())
                                   .getResultList();

        assertTrue("Result of [" + jpql + "] on key-value = (" + ATTR_EMOTION + "," + value
                + ") and key-value=("+ ATTR_SINCE + "," + SINCE + ") should be empty",
                result2.isEmpty());
    }

    public void testAddRemoveAttribute() {
        em.getTransaction().begin();
        People p1 = em.find(People.class, SSN[0]);
        String jpql = "select r from PersistentRelation r where r.source = :node";
        List<PersistentRelation> r = em.createQuery(jpql, PersistentRelation.class)
                            .setHint(QueryHints.HINT_IGNORE_PREPARED_QUERY, true)
                            .setParameter("node", p1)
                            .getResultList();
        assertFalse(r.isEmpty());
        r.get(0).addAttribute("new-key", "new-value");
        em.getTransaction().commit();
        em.clear();

        em.getTransaction().begin();
        jpql = "select r from PersistentRelation r join r.attrs a where key(a) = :key";
        Relation newR = em.createQuery(jpql, PersistentRelation.class)
                          .setParameter("key", "new-key")
                          .getSingleResult();
        assertNotNull(newR);
        assertEquals("new-value", newR.getAttribute("new-key"));
        newR.removeAttribute("new-key");
        em.getTransaction().commit();

        em.getTransaction().begin();
        jpql = "select r from PersistentRelation r join r.attrs a where key(a) = :key";
        try {
            newR = em.createQuery(jpql, PersistentRelation.class)
                          .setParameter("key", "new-key")
                          .getSingleResult();
            fail(jpql + " with new-key expected no result");
        } catch (NoResultException nre) {
            // this is what is expected
        } finally {
            em.getTransaction().rollback();
        }
    }

    boolean isPopulated() {
        return em.createQuery("select count(p) from People p", Long.class).getSingleResult() > 0;
    }

    /**
     * Creates a typical graph of People and Cities. The tests are sensitive to
     * the actual values and relations set in in this method.
     */
    PersistentGraph<Object> createData() {
        PersistentGraph<Object> graph = new RelationGraph<>();

        em.getTransaction().begin();

        People[] people = new People[SSN.length];
        for (int i = 0; i < SSN.length; i++) {
            People p = new People();
            graph.add(p);
            p.setSsn(SSN[i]);
            p.setName(PERSON_NAMES[i]);
            people[i] = p;
        }
        City[] cities = new City[CITY_NAMES.length];
        for (int i = 0; i < CITY_NAMES.length; i++) {
            City c = new City();
            graph.add(c);
            c.setName(CITY_NAMES[i]);
            cities[i] = c;
        }
        for (int i = 0; i < people.length; i++) {
            for (int j = 0; j < people.length; j++) {
                if (EMOTIONS[i][j] != null) {
                    Relation<People, People> r = graph.link(people[i], people[j])
                                 .addAttribute(ATTR_EMOTION, EMOTIONS[i][j]);
                    if (i == 0 && j == 2) {
                        r.addAttribute(ATTR_SINCE, SINCE);
                    }
                }
            }
        }
        for (int i = 0; i < cities.length; i++) {
            for (int j = 0; j < cities.length; j++) {
                graph.link(cities[i], cities[j]).addAttribute(ATTR_DISTANCE, ATTR_DISTANCE_VALUE[i][j]);
            }
        }

        for (int i = 0; i < people.length; i++) {
            graph.link(people[i], cities[i % CITY_NAMES.length]);
        }
        em.persist(graph);
        em.getTransaction().commit();

        return graph;
    }

    void assertDataEquals(Graph<Object> graph, People[] people, City[] cities) {
        assertEquals(SSN.length, people.length);
        assertEquals(CITY_NAMES.length, cities.length);

        for (int i = 0; i < people.length; i++) {
            People p = people[i];
            assertEquals(SSN[i], p.getSsn());
            assertEquals(PERSON_NAMES[i], p.getName());
        }
        for (int i = 0; i < cities.length; i++) {
            City c = cities[i];
            assertEquals(CITY_NAMES[i], c.getName());
        }
        for (int i = 0; i < people.length; i++) {
            People p1 = people[i];
            for (int j = 0; j < people.length; j++) {
                People p2 = people[j];
                Relation<People, People> r = graph.getRelation(p1,p2);
                if (EMOTIONS[i][j] != null) {
                    assertNotNull(r);
                    assertEquals(EMOTIONS[i][j].toString(), r.getAttribute(ATTR_EMOTION));
                } else {
                    assertNull(r);
                }
            }
        }
        for (int i = 0; i < cities.length; i++) {
            City c1 = cities[i];
            for (int j = 0; j < cities.length; j++) {
                City c2 = cities[j];
                Relation<City, City> r12 = graph.getRelation(c1,c2);
                assertNotNull(r12);
                assertEquals(""+ATTR_DISTANCE_VALUE[i][j], r12.getAttribute(ATTR_DISTANCE));
            }
        }

        for (int i = 0; i < people.length; i++) {
            People p = people[i];
            for (int j = 0; j < cities.length; j++) {
                City c = cities[j];
                Relation<People, City> r = graph.getRelation(p,c);
                if (i % CITY_NAMES.length == j) {
                    assertNotNull(r);
                } else {
                    assertNull(r);
                }
            }

        }
    }

    int indexOf(People p) {
        for (int i = 0; i < SSN.length; i++) {
            if (SSN[i] == p.getSsn())
                return i;
        }
        return -1;
    }

    int indexOf(City c) {
        for (int i = 0; i < CITY_NAMES.length; i++) {
            if (CITY_NAMES[i].equals(c.getName()))
                return i;
        }
        return -1;
    }
}
