package net.northking.cctp.maven.gen;

import net.northking.cctp.maven.analyse.entity.JavaClassRef;
import net.northking.cctp.maven.analyse.entity.TableRef;
import net.northking.cctp.maven.analyse.util.StringUtil;
import org.apache.maven.plugin.MojoExecutionException;

import java.io.File;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成器
 *
 * @author xiusong.xie
 * @since 1.0
 */
public class CCTPGenerator extends VMGenerator
{

  /**
   * 版本号
   */
  private static final String VERSION = "1.0";

  /**
   * 作者
   */
  private static final String AUTHOR = "maven-cctp-plugin";


  /**
   * 工程目录
   */
  private File projectDir;

  /**
   * 基础包名
   */
  private String basePackage;

  /**
   * 构造函数
   *
   * @param projectDir  工程所在目录
   * @param basePackage 基础包名
   */
  public CCTPGenerator(File projectDir, String basePackage)
  {
    this.projectDir = projectDir;
    this.basePackage = basePackage;
  }


  public void genEntity(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.ENTITY, javaClassRef);
  }

  public void genTenantEntity(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.TENANT_ENTITY, javaClassRef);
  }

  public void genJpa(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.JPA, javaClassRef);
    genCode(GenCodeTaskEnum.JPA_ENTITY, javaClassRef);
  }

  public void genTenantJpa(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.TENANT_JPA, javaClassRef);
    genCode(GenCodeTaskEnum.TENANT_JPA_ENTITY, javaClassRef);
  }

  public void genMybatisMapperBase(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.MAPPER, javaClassRef);
    genCode(GenCodeTaskEnum.MAPPER_XML, javaClassRef);
  }

  public void genTenantMybatisMapperBase(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.MAPPER, javaClassRef);
    genCode(GenCodeTaskEnum.TENANT_MAPPER_XML, javaClassRef);
  }

  public void genMybatisMapperExt(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.DAO, javaClassRef);
    genCode(GenCodeTaskEnum.DAO_XML, javaClassRef);
  }

  public void genMybatisService(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.SERVICE, javaClassRef);
    genCode(GenCodeTaskEnum.SERVICE_IMPL, javaClassRef);
  }

  public void genTenantMybatisService(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.SERVICE, javaClassRef);
    genCode(GenCodeTaskEnum.TENANT_SERVICE_IMPL, javaClassRef);
  }

  public void genHttpApi(TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = createJavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.API_RESTFUL, javaClassRef);
    genCode(GenCodeTaskEnum.API_QUERY, javaClassRef);
    genCode(GenCodeTaskEnum.API_BATCH, javaClassRef);

    genCode(GenCodeTaskEnum.API_DTO_ADD, javaClassRef);
    genCode(GenCodeTaskEnum.API_DTO_UPDATE, javaClassRef);
    genCode(GenCodeTaskEnum.API_DTO_QUERY, javaClassRef);
    genCode(GenCodeTaskEnum.API_DTO_DETAIL, javaClassRef);

    genCode(GenCodeTaskEnum.API_SERVICE, javaClassRef);
    genCode(GenCodeTaskEnum.API_SERVICE_IMPL, javaClassRef);
  }

  public void genMybatisAll(final TableRef tableRef) throws MojoExecutionException
  {
    genEntity(tableRef);
    genMybatisMapperBase(tableRef);
    genMybatisMapperExt(tableRef);
    genMybatisService(tableRef);
  }

  public void genTenantMybatisAll(final TableRef tableRef) throws MojoExecutionException
  {
    genTenantEntity(tableRef);
    genTenantMybatisMapperBase(tableRef);
    genMybatisMapperExt(tableRef);
    genTenantMybatisService(tableRef);
  }

  public void genMainCode(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);

    genCode(GenCodeTaskEnum.ENTITY, javaClassRef);
    genCode(GenCodeTaskEnum.MAPPER, javaClassRef);
    genCode(GenCodeTaskEnum.MAPPER_XML, javaClassRef);
    genCode(GenCodeTaskEnum.DAO, javaClassRef);
    genCode(GenCodeTaskEnum.DAO_XML, javaClassRef);
    genCode(GenCodeTaskEnum.SERVICE, javaClassRef);
    genCode(GenCodeTaskEnum.SERVICE_IMPL, javaClassRef);
  }

  public void genDtoCode(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.DTO, javaClassRef);
  }

  public void genVueCode(final TableRef tableRef) throws MojoExecutionException
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_ENTITY_JS, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_INDEX, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_DETAIL, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_ADD, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_EDIT, javaClassRef);
    genCode(GenCodeTaskEnum.VUE_ROUTER, javaClassRef);
  }

  private JavaClassRef createJavaClassRef(final TableRef tableRef)
  {
    JavaClassRef javaClassRef = new JavaClassRef(tableRef);
    initDataMap(tableRef, javaClassRef);
    return javaClassRef;
  }

  public void genCode(GenCodeTaskEnum genCodeTask, final JavaClassRef javaClassRef) throws MojoExecutionException
  {
    boolean isOverride = genCodeTask.isOverride();
    String vmTemplate = genCodeTask.getVmTemplate();
    String filePath = projectDir.getAbsolutePath();
    if ("java".equalsIgnoreCase(genCodeTask.getType()))
    {
      filePath += Constants.SRC_MAIN_JAVA + StringUtil.packageToFilePath(basePackage + genCodeTask.getPathName());
    } else if ("resource".equalsIgnoreCase(genCodeTask.getType()))
    {
      filePath += Constants.SRC_MAIN_RESOURCES + genCodeTask.getPathName();
    }else {
      filePath += basePackage;
    }
    if (genCodeTask.isSubPackage())
    {
      filePath += "/" + javaClassRef.getClassName();
    }
    String fileName = javaClassRef.getClassName() + genCodeTask.getPostfix();
    try
    {
      this.genFile(DATA_MAP, vmTemplate, filePath, fileName, isOverride);
    } catch (Exception e)
    {
      throw new MojoExecutionException(e.getMessage(), e);
    }
  }

  /**
   * 数据
   */
  private static Map<String, Object> DATA_MAP = new HashMap<>();

  /**
   * 构造数据
   *
   * @param tableRef     数据库表对象
   * @param javaClassRef JAVA类对象
   * @return 数据
   */
  private Map<String, Object> initDataMap(final TableRef tableRef, final JavaClassRef javaClassRef)
  {
    if (DATA_MAP.size() == 0)
    {
      DATA_MAP.put("Year", Calendar.getInstance().get(Calendar.YEAR));
      DATA_MAP.put("Version", VERSION);
      DATA_MAP.put("Author", AUTHOR);
      DATA_MAP.put("entityPackage", basePackage + Constants.PACKAGE_ENTITY);
      DATA_MAP.put("jpaPackage", basePackage + Constants.PACKAGE_JAP);
      DATA_MAP.put("mapperPackage", basePackage + Constants.PACKAGE_MYBATIS_MAPPER);
      DATA_MAP.put("daoPackage", basePackage + Constants.PACKAGE_MYBATIS_DAO);
      DATA_MAP.put("adapterPackage", basePackage + Constants.PACKAGE_MYBATIS_ADAPTER);
      DATA_MAP.put("servicePackage", basePackage + Constants.PACKAGE_MYBATIS_SERVICE);
      DATA_MAP.put("srvImplPackage", basePackage + Constants.PACKAGE_MYBATIS_IMPL);
      DATA_MAP.put("dtoPackage", basePackage + Constants.PACKAGE_DTO);
      DATA_MAP.put("apiPackage", basePackage + Constants.PACKAGE_API);
      DATA_MAP.put("genPackage", basePackage + Constants.PACKAGE_GEN_CODE);
      DATA_MAP.put("DEFAULT_SCHEMA", "${defaultSchema}");
      DATA_MAP.put("SCHEMA_SUFFIX", "${schemaSuffix}");
      DATA_MAP.put("TABLE_SUFFIX", "${tableSuffix}");
      DATA_MAP.put("DOLLAR_MARK", "$");
    }
    DATA_MAP.put("tableRef", tableRef);
    DATA_MAP.put("javaClassRef", javaClassRef);
    return DATA_MAP;
  }
}
