package sqlancer.tidb.ast;

import java.util.List;

import sqlancer.Randomly;

public class TiDBFunctionCall implements TiDBExpression {

	private TiDBFunction function;
	private List<TiDBExpression> args;

	// https://pingcap.github.io/docs/stable/reference/sql/functions-and-operators/numeric-functions-and-operators/
	public static enum TiDBFunction {
		
//		POW(2),
//		POWER(2),
//		EXP(1),
//		SQRT(1),
//		LN(1),
//		LOG(1),
//		LOG2(1),
//		LOG10(1),
//		PI(0),
//		TAN(1),
//		COT(1),
//		SIN(1),
//		COS(1),
//		ATAN(1),
//		ATAN2(2),
//		ACOS(1),
//		RADIANS(1),
//		DEGREES(1),
//		MOD(2),
//		ABS(1),
//		CEIL(1),
//		CEILING(1),
//		FLOOR(1),
//		ROUND(1),
////		RAND(1),
//		SIGN(1),
////		CONV()
//		// TRUNCATE(),
//		CRC32(1),
		
		
		// https://pingcap.github.io/docs/stable/reference/sql/functions-and-operators/bit-functions-and-operators/
		BIT_COUNT(1),
		
		// https://pingcap.github.io/docs/stable/reference/sql/functions-and-operators/information-functions/
		CONNECTION_ID(0),
		CURRENT_USER(0),
		DATABASE(0),
//		FOUND_ROWS(0), <-- non-deterministic
//		LAST_INSERT_ID(0), <-- non-deterministic
//		ROW_COUNT(0),  <-- non-deterministic
		SCHEMA(0),
		SESSION_USER(0),
		SYSTEM_USER(0),
		USER(0),
		VERSION(0),
		
		TIDB_VERSION(0),
		
		IF(3),
		IFNULL(2),
		NULLIF(2),
		
		ASCII(1),
		BIN(1),
		BIT_LENGTH(1),
		// https://github.com/pingcap/tidb/issues/15847
//		CHAR(1),
		CHAR_LENGTH(1),
		CHARACTER_LENGTH(1),
		CONCAT(1, true),
		CONCAT_WS(2, true),
		ELT(2, true),
		EXPORT_SET(0) {
			@Override
			public int getNrArgs() {
				return Randomly.fromOptions(3, 4, 5);
			}
		}
		;
		
		private int nrArgs;
		private boolean isVariadic;
		
		TiDBFunction(int nrArgs) {
			this.nrArgs = nrArgs;
		}
	
		TiDBFunction(int nrArgs, boolean isVariadic) {
			this.nrArgs = nrArgs;
			this.isVariadic = true;
		}
		
		public static TiDBFunction getRandom() {
			return Randomly.fromOptions(values());
		}
		
		public int getNrArgs() {
			return nrArgs + (isVariadic() ? Randomly.smallNumber() : 0);
		}
		
		public boolean isVariadic() {
			return isVariadic;
		}
		
	}
	
	public TiDBFunctionCall(TiDBFunction function, List<TiDBExpression> args) {
		this.function = function;
		this.args = args;
	}
	
	public List<TiDBExpression> getArgs() {
		return args;
	}
	
	public TiDBFunction getFunction() {
		return function;
	}
	
}

@@ -1296,16 +1296,38 @@
 (2),%0A%09%09%0A
+%09%09// string functions%0A
 %09%09ASCII(
@@ -1627,16 +1627,252 @@
 %09%09%09%7D%0A%09%09%7D
+,%0A%09%09// %5B...%5D%0A%09%09REPLACE(3),%0A%09%09REVERSE(1),%0A%09%09RIGHT(2),%0A%09%09// RPAD TODO%0A%09%09RTRIM(1),%0A%09%09SPACE(1),%0A%09%09STRCMP(2),%0A%09%09SUBSTRING(2), // TODO: support other versions%0A%09%09SUBSTRING_INDEX(3),%0A%09%09TO_BASE64(1),%0A%09%09TRIM(1),%0A%09%09UCASE(1),%0A%09%09UNHEX(1),%0A%09%09UPPER(1)
 %0A%09%09;%0A%09%09%0A

Add support for additional string functions