package tryslim3.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.FilterCriterion;
import org.slim3.datastore.InMemoryFilterCriterion;
import org.slim3.util.BeanUtil;
import org.slim3.util.BooleanUtil;
import org.slim3.util.DateUtil;
import org.slim3.util.IntegerUtil;
import org.slim3.util.StringUtil;

import tryslim3.meta.Crud2Meta;
import tryslim3.model.Crud2;
import tryslim3.model.Crud2Form;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

public class Crud2Service {
    private static final Logger logger =
        Logger.getLogger(Crud2Service.class.getName());

    private Crud2Meta meta = Crud2Meta.get();

    public Crud2 get(Key key, Long version) {
        return Datastore.get(meta, key, version);
    }

    public List<Crud2> getAll() {
        // return Datastore.query(meta).sort(meta.date.asc,
        // meta.key.asc).asList();
        Crud2Form form = new Crud2Form();
        return getList(form);
    }

    public void insert(Crud2 crud2) {
        Transaction tx = Datastore.beginTransaction();
        Datastore.put(tx, crud2);
        Datastore.commit(tx);
    }

    public Crud2 update(Key key, Long version, Map<String, Object> input) {
        Transaction tx = Datastore.beginTransaction();
        Crud2 crud2 = Datastore.get(tx, meta, key, version);
        BeanUtil.copy(input, crud2);
        Datastore.put(tx, crud2);
        Datastore.commit(tx);
        return crud2;
    }

    public void delete(Key key, Long version) {
        Transaction tx = Datastore.beginTransaction();
        Crud2 crud2 = Datastore.get(tx, meta, key, version);
        Datastore.delete(tx, crud2.getKey());
        Datastore.commit(tx);
    }

    public List<Crud2> getList(Crud2Form form) {
        List<FilterCriterion> gaeFilterList = new ArrayList<FilterCriterion>();
        List<InMemoryFilterCriterion> memoryFilterList =
            new ArrayList<InMemoryFilterCriterion>();

        // 検索条件の組み立て
        if (!StringUtil.isEmpty(form.getSearchTitle())) {
            memoryFilterList.add(meta.title.contains(form.getSearchTitle()));
        }
        if (!StringUtil.isEmpty(form.getSearchContent())) {
            memoryFilterList
                .add(meta.content.contains(form.getSearchContent()));
        }
        if (!StringUtil.isEmpty(form.getSearchDateFrom())) {
            memoryFilterList.add(meta.date.greaterThanOrEqual(DateUtil.toDate(
                form.getSearchDateFrom(),
                "yyyy/MM/dd")));
        }
        if (!StringUtil.isEmpty(form.getSearchDateTo())) {
            memoryFilterList.add(meta.date.lessThanOrEqual(DateUtil.toDate(form
                .getSearchDateTo(), "yyyy/MM/dd")));
        }
        if (!StringUtil.isEmpty(form.getSearchNumberFrom())) {
            memoryFilterList.add(meta.number.greaterThanOrEqual(IntegerUtil
                .toInteger(form.getSearchNumberFrom())));
        }
        if (!StringUtil.isEmpty(form.getSearchNumberTo())) {
            memoryFilterList.add(meta.number.lessThanOrEqual(IntegerUtil
                .toInteger(form.getSearchNumberTo())));
        }
        if (!StringUtil.isEmpty(form.getSearchFlag())) {
            // gaeFilterList.add(meta.flag.equal(BooleanUtil.toBoolean(form
            // .getSearchFlag())));
            memoryFilterList.add(meta.flag.equal(BooleanUtil.toBoolean(form
                .getSearchFlag())));
        }

        // デバッグログ
        // logger.info(ToStringBuilder.reflectionToString(gaeFilterList));
        // logger.info(ToStringBuilder.reflectionToString(memoryFilterList));

        return Datastore.query(meta).filter(
            gaeFilterList.toArray(new FilterCriterion[] {})).filterInMemory(
            memoryFilterList.toArray(new InMemoryFilterCriterion[] {})).sort(
            meta.title.asc,
            meta.key.asc).asList();
    }
}