/**
 * Copyright (C) 2010 Olafur Gauti Gudmundsson
 *
 * Licensed 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.mongodb.morphia;


import com.mongodb.BasicDBObject;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mongodb.morphia.annotations.Embedded;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Reference;
import org.mongodb.morphia.mapping.Mapper;
import org.mongodb.morphia.testmodel.Rectangle;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;


/**
 * @author Scott Hernandez
 */
public class TestIdField extends TestBase {

    @Entity
    private static class ReferenceAsId {
        @Id
        @Reference
        private Rectangle id;

        protected ReferenceAsId() {
        }

        public ReferenceAsId(final Rectangle key) {
            id = key;
        }
    }

    @Entity
    private static class KeyAsId {
        @Id
        private Key<?> id;

        protected KeyAsId() {
        }

        public KeyAsId(final Key<?> key) {
            id = key;
        }
    }

    @Entity
    private static class MapAsId {
        @Id
        private final Map<String, String> id = new HashMap<String, String>();
    }

    @Entity(noClassnameStored = true)
    public static class EmbeddedId {

        @Id
        private MyId id;
        private String data;

        public EmbeddedId() {
        }

        public EmbeddedId(final MyId myId, final String data) {
            id = myId;
            this.data = data;
        }
    }

    @Embedded
    public static class MyId {
        private String myIdPart1;
        private String myIdPart2;

        public MyId() {
        }

        public MyId(final String myIdPart1, final String myIdPart2) {
            this.myIdPart1 = myIdPart1;
            this.myIdPart2 = myIdPart2;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            final MyId myId = (MyId) o;

            if (!myIdPart1.equals(myId.myIdPart1)) {
                return false;
            }
            if (!myIdPart2.equals(myId.myIdPart2)) {
                return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int result = myIdPart1.hashCode();
            result = 31 * result + myIdPart2.hashCode();
            return result;
        }
    }

    @Test
    @Ignore("need to set the _db in the dbRef for this to work... see issue 90")
    public void testReferenceAsId() throws Exception {
        getMorphia().map(ReferenceAsId.class);

        final Rectangle r = new Rectangle(1, 1);
        final Key<Rectangle> rKey = getDs().save(r);

        final ReferenceAsId rai = new ReferenceAsId(r);
        final Key<ReferenceAsId> raiKey = getDs().save(rai);
        final ReferenceAsId raiLoaded = getDs().get(ReferenceAsId.class, rKey);
        assertNotNull(raiLoaded);
        assertEquals(raiLoaded.id.getArea(), r.getArea(), 0);

        assertNotNull(raiKey);
    }

    @Test
    public void testKeyAsId() throws Exception {
        getMorphia().map(KeyAsId.class);

        final Rectangle r = new Rectangle(1, 1);
        //        Rectangle r2 = new Rectangle(11,11);

        final Key<Rectangle> rKey = getDs().save(r);
        //        Key<Rectangle> r2Key = ds.save(r2);
        final KeyAsId kai = new KeyAsId(rKey);
        final Key<KeyAsId> kaiKey = getDs().save(kai);
        final KeyAsId kaiLoaded = getDs().get(KeyAsId.class, rKey);
        assertNotNull(kaiLoaded);
        assertNotNull(kaiKey);
    }

    @Test
    public void testMapAsId() throws Exception {
        getMorphia().map(MapAsId.class);

        final MapAsId mai = new MapAsId();
        mai.id.put("test", "string");
        final Key<MapAsId> maiKey = getDs().save(mai);
        final MapAsId maiLoaded = getDs().get(MapAsId.class, new BasicDBObject("test", "string"));
        assertNotNull(maiLoaded);
        assertNotNull(maiKey);
    }

    @Test
    public void testIdFieldNameMapping() throws Exception {
        final Rectangle r = new Rectangle(1, 12);
        final BasicDBObject dbObj = (BasicDBObject) getMorphia().toDBObject(r);
        assertFalse(dbObj.containsField("id"));
        assertTrue(dbObj.containsField(Mapper.ID_KEY));
        assertEquals(4, dbObj.size()); //_id, h, w, className
    }

    @Test
    public void embeddedIds() {
        final MyId id = new MyId("1", "2");

        final EmbeddedId a = new EmbeddedId(id, "data");
        final EmbeddedId b = new EmbeddedId(new MyId("2", "3"), "data, too");

        getDs().save(a);
        getDs().save(b);

        assertEquals(a.data, getDs().get(EmbeddedId.class, id).data);

        final EmbeddedId embeddedId = getDs().find(EmbeddedId.class).field("_id").in(Arrays.asList(id)).asList().get(0);
        Assert.assertEquals(a.data, embeddedId.data);
        Assert.assertEquals(a.id, embeddedId.id);
    }
}
@@ -706,33 +706,8 @@
 rt;%0A
-import org.junit.Ignore;%0A
 impo
@@ -725,16 +725,16 @@
 t.Test;%0A
+
 import o
@@ -868,58 +868,8 @@
 Id;%0A
-import org.mongodb.morphia.annotations.Reference;%0A
 impo
@@ -1294,261 +1294,8 @@
  %7B%0A%0A
-    @Entity%0A    private static class ReferenceAsId %7B%0A        @Id%0A        @Reference%0A        private Rectangle id;%0A%0A        protected ReferenceAsId() %7B%0A        %7D%0A%0A        public ReferenceAsId(final Rectangle key) %7B%0A            id = key;%0A        %7D%0A    %7D%0A%0A
     
@@ -1391,15 +1391,13 @@
   pr
-otec
+iva
 te
-d
  Key
@@ -2965,16 +2965,16 @@
 result;%0A
+
         
@@ -2986,637 +2986,8 @@
  %7D%0A%0A
-    @Test%0A    @Ignore(%22need to set the _db in the dbRef for this to work... see issue 90%22)%0A    public void testReferenceAsId() throws Exception %7B%0A        getMorphia().map(ReferenceAsId.class);%0A%0A        final Rectangle r = new Rectangle(1, 1);%0A        final Key%3CRectangle%3E rKey = getDs().save(r);%0A%0A        final ReferenceAsId rai = new ReferenceAsId(r);%0A        final Key%3CReferenceAsId%3E raiKey = getDs().save(rai);%0A        final ReferenceAsId raiLoaded = getDs().get(ReferenceAsId.class, rKey);%0A        assertNotNull(raiLoaded);%0A        assertEquals(raiLoaded.id.getArea(), r.getArea(), 0);%0A%0A        assertNotNull(raiKey);%0A    %7D%0A%0A
     

remove old ignored test