/**
 *
 * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
 *
 * 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 com.speedment.generator.standard.manager;

import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;
import com.speedment.common.codegen.constant.SimpleParameterizedType;
import com.speedment.common.codegen.model.Class;
import com.speedment.common.codegen.model.Constructor;
import com.speedment.common.codegen.model.Field;
import com.speedment.common.codegen.model.File;
import com.speedment.common.codegen.model.Method;
import static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields;
import com.speedment.generator.translator.AbstractEntityAndManagerTranslator;
import com.speedment.runtime.config.Column;
import com.speedment.runtime.config.Table;
import com.speedment.runtime.config.identifier.TableIdentifier;
import com.speedment.runtime.config.trait.HasEnabled;
import com.speedment.runtime.core.manager.AbstractManager;
import java.lang.reflect.Type;
import java.util.Comparator;
import static java.util.stream.Collectors.joining;
import java.util.stream.Stream;

/**
 *
 * @author Emil Forslund
 * @since 2.3.0
 */
public final class GeneratedManagerImplTranslator
    extends AbstractEntityAndManagerTranslator<Class> {

    public final static String ENTITY_COPY_METHOD_NAME = "entityCopy",
        ENTITY_CREATE_METHOD_NAME = "entityCreate",
        FIELDS_METHOD = "fields",
        PRIMARY_KEYS_FIELDS_METHOD = "primaryKeyFields";

    public GeneratedManagerImplTranslator(Table table) {
        super(table, Class::of);
    }

    @Override
    protected Class makeCodeGenModel(File file) {

        return newBuilder(file, getSupport().generatedManagerImplName())
            /**
             * The table specific methods.
             */
            .forEveryTable((clazz, table) -> {
                clazz
                    .public_()
                    .abstract_()
                    .setSupertype(SimpleParameterizedType.create(
                        table.isView()
                            ? AbstractViewManager.class
                            : AbstractManager.class,
                        getSupport().entityType()
                    ))
                    .add(getSupport().generatedManagerType())
                    .add(Field.of("tableIdentifier", SimpleParameterizedType.create(TableIdentifier.class, getSupport().entityType())).private_().final_())
                    .add(Constructor.of().protected_()
                        .add("this.tableIdentifier = " + TableIdentifier.class.getSimpleName() + ".of("
                            + Stream.of(getSupport().dbmsOrThrow().getId(), getSupport().schemaOrThrow().getId(), getSupport().tableOrThrow().getId())
                                .map(s -> "\"" + s + "\"").collect(joining(", "))
                            + ");")
                    )
                    .add(Method.of("getTableIdentifier", SimpleParameterizedType.create(TableIdentifier.class, getSupport().entityType()))
                        .public_().add(OVERRIDE)
                        .add("return tableIdentifier;")
                    )
                    .add(generateFields(getSupport(), file, FIELDS_METHOD, () -> table.columns().sorted(Comparator.comparing(Column::getOrdinalPosition))))
                    .add(generateFields(getSupport(), file, PRIMARY_KEYS_FIELDS_METHOD,
                        () -> table.primaryKeyColumns()
                            .filter(HasEnabled::test)
                            .map(pk -> pk.findColumn())
                            .filter(o -> o.isPresent())
                            .map(o -> o.get())
                    ));
            })
            .build();
    }

    @Override
    protected String getJavadocRepresentText() {
        return "The generated base implementation for the manager of every {@link "
            + getSupport().entityType().getTypeName() + "} entity.";
    }

    @Override
    protected String getClassOrInterfaceName() {
        return getSupport().generatedManagerImplName();
    }

    @Override
    public boolean isInGeneratedPackage() {
        return true;
    }

    public Type getImplType() {
        return getSupport().managerImplType();
    }

    private static boolean isPrimaryKey(Column column) {
        return column.getParentOrThrow().findPrimaryKeyColumn(column.getId()).isPresent();
    }
}

@@ -679,93 +679,8 @@
 r;%0A%0A
-import static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;%0A
 impo
@@ -840,266 +840,9 @@
 del.
-Constructor;%0Aimport com.speedment.common.codegen.model.Field;%0Aimport com.speedment.common.codegen.model.File;%0Aimport com.speedment.common.codegen.model.Method;%0Aimport static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields
+*
 ;%0Aim
@@ -1064,24 +1064,77 @@
 Identifier;%0A
+import com.speedment.runtime.config.trait.HasColumn;%0A
 import com.s
@@ -1245,59 +1245,337 @@
 ort 
-java.lang.reflect.Type;%0Aimport java.util.Comparator
+com.speedment.runtime.core.manager.AbstractViewManager;%0A%0Aimport java.util.Comparator;%0Aimport java.util.Optional;%0Aimport java.util.stream.Stream;%0A%0Aimport static com.speedment.common.codegen.constant.DefaultAnnotationUsage.OVERRIDE;%0Aimport static com.speedment.generator.standard.internal.util.GenerateMethodBodyUtil.generateFields
 ;%0Aim
@@ -1626,40 +1626,8 @@
 ing;
-%0Aimport java.util.stream.Stream;
 %0A%0A/*
@@ -1817,100 +1817,8 @@
 ring
- ENTITY_COPY_METHOD_NAME = %22entityCopy%22,%0A        ENTITY_CREATE_METHOD_NAME = %22entityCreate%22,
 %0A   
@@ -1836,16 +1836,29 @@
 _METHOD 
+             
 = %22field
@@ -2167,18 +2167,83 @@
        /
-**
+///////////////////////////////////////////////////////////////////
 %0A       
@@ -2247,18 +2247,18 @@
         
- *
+//
  The tab
@@ -2277,17 +2277,20 @@
 methods.
-%0A
+    
         
@@ -2294,17 +2294,117 @@
         
-*
+                   //%0A            ///////////////////////////////////////////////////////////////////
 /%0A      
@@ -4142,17 +4142,19 @@
 map(
-pk -%3E pk.
+HasColumn::
 find
@@ -4159,18 +4159,16 @@
 ndColumn
-()
 )%0A      
@@ -4197,23 +4197,26 @@
 .filter(
-o -%3E o.
+Optional::
 isPresen
@@ -4216,18 +4216,16 @@
 sPresent
-()
 )%0A      
@@ -4255,20 +4255,21 @@
 map(
-o -%3E o.
+Optional::
 get
-()
 )%0A  
@@ -4771,248 +4771,7 @@
    %7D
-%0A%0A    public Type getImplType() %7B%0A        return getSupport().managerImplType();%0A    %7D%0A%0A    private static boolean isPrimaryKey(Column column) %7B%0A        return column.getParentOrThrow().findPrimaryKeyColumn(column.getId()).isPresent();%0A    %7D
 %0A%7D%0A

Clean up manager class