package cn.orm.util.builder.base;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

import cn.util.core.TypeKit;

public class SQLInsertion {

	private StringBuilder builder = null;		// main builder
	private StringJoiner joiner = null;			// main joiner
	
	/***
	 * Constructor
	 */
	public SQLInsertion() {
		builder = new StringBuilder().append("INSERT ");
	}
	
	/***
	 * Which table to insert into
	 * @param tableName		table name
	 * @return				insert
	 */
	public SQLInsertion intoTable(String tableName) {
		builder.append("INTO ").append(tableName).append(' ');
		return this;
	}
	
	/***
	 * Which columns to insert into
	 * @param columns		column names
	 * @return				insert
	 */
	public SQLInsertion intoColumns(String... columns) {
		builder.append('(');
		StringJoiner valueJoiner = new StringJoiner(", ");
		for (String col : columns) {
			valueJoiner.add('`' + col + '`');
		}
		builder.append(valueJoiner.toString()).append(") ");
		return this;
	}
	/***
	 * Which columns to insert into
	 * @param columns		column names
	 * @return				insert
	 */
	public SQLInsertion intoColumns(String columns) {
		builder.append('(').append(columns).append(") ");
		return this;
	}
	/**插入多个？ 无验证*/
	public SQLInsertion withValues(int num) {
		if (joiner == null)
			joiner = new StringJoiner("");
		
		StringBuilder valueBuilder = new StringBuilder();
		valueBuilder.append('(');
		
		StringJoiner valueJoiner = new StringJoiner("");
		for (int i=0; i<num; ++i) {
			if(valueJoiner.length() > 0) {
				valueJoiner.add(",");
			}
			valueJoiner.add("?");
		}
		
		valueBuilder.append(valueJoiner.toString());
		valueBuilder.append(')');
		
		joiner.add(valueBuilder.toString());
		
		return this;
	}
	/***
	 * What values to insert
	 * @param values		values
	 * @return				insert
	 */
	public SQLInsertion withValues(Object... values) {
		if (joiner == null)
			joiner = new StringJoiner(", ");
		
		StringBuilder valueBuilder = new StringBuilder();
		StringJoiner valueJoiner = new StringJoiner(",");
		valueBuilder.append('(');
		for (Object val : values) {
			valueJoiner.add('\"' + TypeKit.objToStr(val) + '\"');
		}
		valueBuilder.append(valueJoiner.toString());
		valueBuilder.append(')');
		
		joiner.add(valueBuilder.toString());
		
		return this;
	}
	
	/***
	 * What values to insert
	 * - This is to let you insert integers and other types in improve performance
	 * - make sure your values match the number of columns you supplied before 
	 * @param values		values
	 * @return				insert
	 */
	public SQLInsertion withValues(Object values) {
		if (joiner == null)
			joiner = new StringJoiner(", ");
		joiner.add('(' + TypeKit.objToStr(values) + ')');
		return this;
	}
	
	/***
	 * Reset insert
	 * @return				insert
	 */
	public SQLInsertion clear() {
		builder = new StringBuilder().append("INSERT ");
		joiner = null;
		return this;
	}
	
	/***
	 * Return the final query
	 * @return 				insert string
	 */
	public String create() {
		return toString();
	}
	
	/***
	 * Return the final query
	 */
	@Override
	public String toString() {
		return builder
				.append((joiner == null) ? "" : "VALUES " + joiner.toString())
				.toString().trim();
	}
	/////////////////////
	public SQLInsertion intoColumns(List<String> columns) {
		builder.append('(');
		StringJoiner valueJoiner = new StringJoiner(", ");
		for (String col : columns) {
			valueJoiner.add('`' + col + '`');
		}
		builder.append(valueJoiner.toString()).append(") ");
		return this;
	}
	public SQLInsertion withValues(List<Object> values) {
		if (joiner == null)
			joiner = new StringJoiner(", ");
		
		StringBuilder valueBuilder = new StringBuilder();
		StringJoiner valueJoiner = new StringJoiner(",");
		valueBuilder.append('(');
		for (Object val : values) {
			valueJoiner.add('\"' + TypeKit.objToStr(val) + '\"');
		}
		valueBuilder.append(valueJoiner.toString());
		valueBuilder.append(')');
		
		joiner.add(valueBuilder.toString());
		
		return this;
	}
	
	/***
	 * Which columns to insert into
	 * @param columns		column names and value
	 * @return				insert
	 */
	public SQLInsertion intoColumnsWithValues(Map<String,Object> mapRecord)
	{
	    List<String> columns = new ArrayList<String>(mapRecord.keySet());
	    List<Object> values = new ArrayList<Object>(mapRecord.values());
	
		builder.append('(');
		StringJoiner column = new StringJoiner(", ");
		for (String col : columns) {
			column.add('`' + col + '`');
		}
		builder.append(column.toString()).append(") ");
				
		if (joiner == null) {
			joiner = new StringJoiner(", ");
		}
		StringBuilder valueBuilder = new StringBuilder();
		StringJoiner valueJoiner = new StringJoiner(",");
		valueBuilder.append('(');
		for (Object val : values) {
			valueJoiner.add('\"' + TypeKit.objToStr(val) + '\"');
		}
		valueBuilder.append(valueJoiner.toString());
		valueBuilder.append(')');
		joiner.add(valueBuilder.toString());
		
		return this;
	}
	
	public static void main(String[] args)
	{
		Map<String,Object> mapRecord = new HashMap<>();
		mapRecord.put("key1", 1);
		mapRecord.put("key2", null);
		String sql = new SQLInsertion()
				.intoTable("dbName")
				.intoColumnsWithValues(mapRecord)
				.create();
        System.out.println(sql);
	}
	
}
