/*
 *  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
 *
 *    https://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.grails.datastore.gorm.mongo

import grails.gorm.annotation.Entity
import grails.gorm.tests.Plant
import grails.mongodb.MongoEntity
import org.apache.grails.data.mongo.core.GrailsDataMongoTckManager
import org.apache.grails.data.testing.tck.base.GrailsDataTckSpec
import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform

/**
 * Created by graemerocher on 20/03/14.
 */
@ApplyDetachedCriteriaTransform
class BatchUpdateDeleteSpec extends GrailsDataTckSpec<GrailsDataMongoTckManager> {

    void setupSpec() {
        manager.domainClasses.addAll([BatchUser, BatchAddress, Plant])
    }

    void "Test that batch delete works"() {
        when: "Some test data"
        createTestData()

        then: "The correct amount of data exists"
        Plant.count() == 6

        when: "a batch delete is executed"
        Plant.where {
            name == ~/Ca+/
        }.deleteAll()
        manager.session.flush()

        then: "The right amount of data is deleted"
        Plant.count() == 4
    }

    void "Test that batch update works"() {
        when: "Some test data"
        createTestData()

        then: "The correct amount of data exists"
        Plant.count() == 6

        when: "a batch delete is executed"
        Plant.where {
            name == ~/Ca+/
        }.updateAll(goesInPatch: true)
        manager.session.flush()

        then: "The right amount of data is deleted"
        Plant.countByGoesInPatch(true) == 2
    }

    void "Test that batch update works with domain properties"() {
        given:
        BatchAddress addressA = new BatchAddress(name: "a").save()
        BatchAddress addressB = new BatchAddress(name: "b").save(flush: true, failOnError: true)
        new BatchUser(address: addressA).save()
        new BatchUser(address: addressA).save()
        new BatchUser(address: addressB).save(flush: true, failOnError: true)
        manager.session.flush()

        when:
        int aCount = BatchUser.where { address == addressA }.count()
        int bCount = BatchUser.where { address == addressB }.count()

        then:
        aCount == 2
        bCount == 1

        when:
        BatchUser.where { address == addressA }.updateAll(address: addressB)
        manager.session.flush()

        boolean addressBUserCount = BatchUser.where { address == addressB }.count() == 3
        boolean addressAUserCount = BatchUser.where { address == addressA }.count() == 0

        then:
        BatchUser.count() == 3
        addressAUserCount
        addressBUserCount
    }

    void createTestData() {
        new Plant(name: "Cabbage").save()
        new Plant(name: "Carrot").save()
        new Plant(name: "Lettuce").save()
        new Plant(name: "Pumpkin").save()
        new Plant(name: "Bamboo").save()
        new Plant(name: "Palm Tree").save(flush: true)
    }
}


@Entity
class BatchAddress implements MongoEntity<BatchAddress> {
    Long id
    String name
    static mapping = {
        version false
    }
}

@Entity
class BatchUser implements MongoEntity<BatchUser> {
    Long id
    BatchAddress address
    static mapping = {
        version false
    }
}