package org.modelmap.example;

import static com.datastax.driver.core.DataType.text;
import static com.datastax.driver.core.DataType.timeuuid;
import static com.datastax.driver.core.schemabuilder.SchemaBuilder.Direction.DESC;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
import static org.modelmap.sample.field.SampleFieldId.EMAIL;
import static org.modelmap.sample.field.SampleFieldId.LOGIN;

import java.time.LocalDate;
import java.util.Collection;
import java.util.Map;

import org.modelmap.core.FieldId;
import org.modelmap.core.FieldInfo;
import org.modelmap.core.FieldModel;
import org.modelmap.sample.field.SampleTag;
import org.modelmap.sample.model.Account;
import org.modelmap.sample.model.SampleModel;
import org.modelmap.sample.model.SampleModelWrapper;
import org.modelmap.sample.model.SampleModels;

import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.extras.codecs.jdk8.LocalDateCodec;

public class LiveCode {

    public static void main(String[] args) {
        intro();
        example1();
        example2();
        exemple3();
    }

    private static void intro() {
        SampleModel model = new SampleModel();
        model.setAccount(new Account());
        model.getAccount().setEmail("parisjug@gmail.com");
        System.out.println(model.getAccount().getEmail());

        FieldModel fieldModel = new SampleModelWrapper(model);
        System.out.println(fieldModel.<String> get(EMAIL));

        fieldModel.set(EMAIL, "parisjug.gmail.com");
        System.out.println(fieldModel.<String> get(EMAIL));
    }

    private static void example1() {
        FieldModel model = SampleModels.wrapper();
        System.out.println(model.<String> get(EMAIL));
        model.stream().forEach(System.out::println);
        Map<FieldId, Object> map = model.stream().collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
        System.out.println(map);
        SampleModelWrapper newModel = new SampleModelWrapper();
        map.entrySet().forEach(e -> newModel.set(e.getKey(), e.getValue()));
        newModel.stream().forEach(System.out::println);
        System.out.println(newModel.getModel().getAccount().getEmail());
    }

    private static void example2() {
        FieldModel model = SampleModels.wrapper();
        Map<FieldId, Object> map = model.stream().collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
        SampleModelWrapper newModel = new SampleModelWrapper();
        map.entrySet().stream().filter(e -> e.getKey().hasTag(SampleTag.ACCOUNT))
                        // .filter(e -> e.getKey().hasTag(SampleTag.USER))
                        .forEach(e -> newModel.set(e.getKey(), e.getValue()));
        newModel.stream().forEach(System.out::println);
    }

    private static void exemple3() {
        FieldModel model = SampleModels.wrapper();
        Create create = SchemaBuilder.createTable("Field").addClusteringColumn(LOGIN.name(), text())
                        .addPartitionKey("snapshot_id", timeuuid());

        stream(model.getFieldInfos()).filter(f -> !f.id().equals(LOGIN))
                        .forEach(f -> create.addColumn(f.id().name(), cqlType(f)));

        Create.Options createWithOptions = create.withOptions().clusteringOrder(LOGIN.name(), DESC);
        System.out.println(createWithOptions);

        Insert insert = QueryBuilder.insertInto("Field");
        model.stream().forEach(e -> insert.value(e.getKey().name(), e.getValue()));
        CodecRegistry codecRegistry = new CodecRegistry();
        codecRegistry.register(LocalDateCodec.instance);
        System.out.println(insert.getQueryString(codecRegistry));
    }

    private static DataType cqlType(FieldInfo info) {
        if (String.class.equals(info.type()))
            return text();
        else if (Boolean.class.equals(info.type()) || Boolean.TYPE.equals(info.type()))
            return DataType.cboolean();
        else if (Long.class.equals(info.type()) || Long.TYPE.equals(info.type()))
            return DataType.cint();
        else if (LocalDate.class.equals(info.type()))
            return DataType.date();
        else if (Enum.class.isAssignableFrom(info.type()))
            return DataType.set(text());
        else if (Collection.class.isAssignableFrom(info.type()))
            return DataType.set(text());
        throw new IllegalArgumentException("unknown type " + info.type() + " for " + info.id());
    }
}

@@ -508,16 +508,44 @@
 til.Map;
+%0Aimport java.util.Map.Entry;
 %0A%0Aimport
@@ -2148,36 +2148,32 @@
 ).collect(toMap(
-Map.
 Entry::getKey, M
@@ -2163,36 +2163,32 @@
 (Entry::getKey, 
-Map.
 Entry::getValue)
@@ -2652,20 +2652,16 @@
 t(toMap(
-Map.
 Entry::g
@@ -2667,20 +2667,16 @@
 getKey, 
-Map.
 Entry::g

optimize import