package sim.lib.functions;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Scanner;

public class VHDLGeneral {

	public static void write2busto1busFunction(String path, String VHDLName, int busSize, String function, boolean cin, boolean cout){
		String fileName = "gates.vhd";
		File file = new File(path+"\\"+fileName);
		boolean written = false;
		try {
			Scanner scanner = new Scanner(file);
			while(scanner.hasNextLine()){
				String line = scanner.nextLine();
				if(line.contains(VHDLName)){
					written = true;
				}
			}
			scanner.close();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		
		if(!written){
			Writer writer = null;
			try {
				writer = new FileWriter(path+"\\"+fileName,true);
				writer.write("\nlibrary IEEE;\n");
				writer.write("use IEEE.STD_LOGIC_1164.ALL;\n");
				writer.write("use IEEE.numeric_std.all;\n");
				
				writer.write("\nentity " + VHDLName + " is\n");
				//if(this.inputSize == 1){
				writer.write("port( x0: in std_logic;\n");
				for(int x = 1; x < busSize; x++){
					writer.write("x" + x + ": in std_logic;\n");
				}
				
				//writer.write("y0: in std_logic;\n");
				for(int x = 0; x < busSize; x++){
					writer.write("y" + x + ": in std_logic;\n");
				}
				
				if (cin)
					writer.write("cin: in std_logic;\n");
				
				for(int x = 0; x < busSize; x++){
					writer.write("F" + x + ": out std_logic");
					if(x != (busSize-1))
						writer.write(";\n");
				}
				
				if(cout)
					writer.write(";\ncout: out std_logic\n");
				
				writer.write(");\n");
				
				writer.write("end "+ VHDLName + ";\n\n");
				
				writer.write("architecture behav of "+ VHDLName + " is\n");
				writer.write("signal x: std_logic_vector(" + (busSize-1) + " downto 0);\n");
				writer.write("signal y: std_logic_vector(" + (busSize-1) + " downto 0);\n");
				if(cin)
					writer.write("signal cin_vect: std_logic_vector(0 downto 0);\n");
				if(cout){
					writer.write("signal f: std_logic_vector(" + busSize + " downto 0);\n");
				}else{
					writer.write("signal f: std_logic_vector(" + (busSize-1) + " downto 0);\n");
				}
				writer.write("begin\n");
				//writer.write("F<=x0");
				/*for(int x = 1; x < busSize; x++){
					writer.write(" and x" + x);
				}*/
				
				for(int x = 0; x < busSize; x++){
					writer.write("x(" + x + ") <= '0' when x" + x + " = 'U' else x" + x + ";\n");
					writer.write("y(" + x + ") <= '0' when y" + x + " = 'U' else y" + x + ";\n");
				}
				if(cin)
					writer.write("cin_vect(0) <= cin;\n");
				
				writer.write(function + "\n"); //f <= x [operation (xor,and,etc)] y  OR f <= unsigned(x) [+,-,etc] unsigned(y)
				for(int x = 0; x < busSize; x++){
					writer.write("f" + x + " <= f(" + x + ");\n");
				}
				if(cout)
					writer.write("cout <= f("+busSize+");\n");
				//writer.write(";\n");
				writer.write("end behav;\n");
				
				writer.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void write2busto1bitFunction(String path, String VHDLName, int busSize, String function){
		String fileName = "gates.vhd";
		File file = new File(path+"\\"+fileName);
		boolean written = false;
		try {
			Scanner scanner = new Scanner(file);
			while(scanner.hasNextLine()){
				String line = scanner.nextLine();
				if(line.contains(VHDLName)){
					written = true;
				}
			}
			scanner.close();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		
		if(!written){
			Writer writer = null;
			try {
				writer = new FileWriter(path+"\\"+fileName,true);
				writer.write("\nlibrary IEEE;\n");
				writer.write("use IEEE.STD_LOGIC_1164.ALL;\n");
				writer.write("use IEEE.numeric_std.all;\n");
				
				writer.write("\nentity " + VHDLName + " is\n");
				//if(this.inputSize == 1){
				writer.write("port( x0: in std_logic;\n");
				for(int x = 1; x < busSize; x++){
					writer.write("x" + x + ": in std_logic;\n");
				}
				
				//writer.write("y0: in std_logic;\n");
				for(int x = 0; x < busSize; x++){
					writer.write("y" + x + ": in std_logic;\n");
				}
				
				writer.write("F: out std_logic\n");	
				
				writer.write(");\n");
				
				writer.write("end "+ VHDLName + ";\n\n");
				
				writer.write("architecture behav of "+ VHDLName + " is\n");
				writer.write("signal x: std_logic_vector(" +(busSize-1) + " downto 0);\n");
				writer.write("signal y: std_logic_vector(" +(busSize-1) + " downto 0);\n");
				writer.write("begin\n");
				//writer.write("F<=x0");
				/*for(int x = 1; x < busSize; x++){
					writer.write(" and x" + x);
				}*/
				
				for(int x = 0; x < busSize; x++){
					writer.write("x(" + x + ") <= x" + x + ";\n");
					writer.write("y(" + x + ") <= y" + x + ";\n");
				}
				/*writer.write(function + "\n"); //f <= x [operation (xor,and,etc)] y  OR f <= unsigned(x) [+,-,etc] unsigned(y)
				for(int x = 0; x < busSize; x++){
					writer.write("f" + x + " <= f(" + x + ");\n");
				}*/
				/*writer.write("if "+function+" then\n");
				writer.write("  f <= '1';\n");
				writer.write("else\n");
				writer.write("  f <= '0';\n");
				writer.write("end if;\n");*/
				writer.write("f <= '1' when "+function+" else '0';\n");
				//writer.write(";\n");
				writer.write("end behav;\n");
				
				writer.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void write1busto1busFunction(String path, String VHDLName, int busSize, String function){
		String fileName = "gates.vhd";
		File file = new File(path+"\\"+fileName);
		boolean written = false;
		try {
			Scanner scanner = new Scanner(file);
			while(scanner.hasNextLine()){
				String line = scanner.nextLine();
				if(line.contains(VHDLName)){
					written = true;
				}
			}
			scanner.close();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		
		if(!written){
			Writer writer = null;
			try {
				writer = new FileWriter(path+"\\"+fileName,true);
				writer.write("\nlibrary IEEE;\n");
				writer.write("use IEEE.STD_LOGIC_1164.ALL;\n");
				writer.write("use IEEE.numeric_std.all;\n");
				
				writer.write("\nentity " + VHDLName + " is\n");
				//if(this.inputSize == 1){
				writer.write("port( x0: in std_logic;\n");
				for(int x = 1; x < busSize; x++){
					writer.write("x" + x + ": in std_logic;\n");
				}
				
				for(int x = 0; x < busSize; x++){
					writer.write("F" + x + ": out std_logic");
					if (x == busSize-1){
						writer.write("\n");
					}else {
						writer.write(";\n");
					}
				}
				
				writer.write(");\n");
				
				writer.write("end "+ VHDLName + ";\n\n");
				
				writer.write("architecture behav of "+ VHDLName + " is\n");
				writer.write("signal x: std_logic_vector(" +(busSize-1) + " downto 0);\n");
				writer.write("signal f: std_logic_vector(" +(busSize-1) + " downto 0);\n");
				writer.write("begin\n");
				//writer.write("F<=x0");
				/*for(int x = 1; x < busSize; x++){
					writer.write(" and x" + x);
				}*/
				
				for(int x = 0; x < busSize; x++){
					writer.write("x(" + x + ") <= x" + x + ";\n");
					//writer.write("y(" + x + ") <= y" + x + ";\n");
				}
				writer.write(function + "\n"); //f <= x [operation (xor,and,etc)] y  OR f <= unsigned(x) [+,-,etc] unsigned(y)
				for(int x = 0; x < busSize; x++){
					writer.write("f" + x + " <= f(" + x + ");\n");
				}
				/*writer.write("if "+function+" then\n");
				writer.write("  f <= '1';\n");
				writer.write("else\n");
				writer.write("  f <= '0';\n");
				writer.write("end if;\n");*/
				//writer.write(";\n");
				writer.write("end behav;\n");
				
				writer.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void write1busto1bitFunction(String path, String VHDLName, int busSize, String function){
		String fileName = "gates.vhd";
		File file = new File(path+"\\"+fileName);
		boolean written = false;
		try {
			Scanner scanner = new Scanner(file);
			while(scanner.hasNextLine()){
				String line = scanner.nextLine();
				if(line.contains(VHDLName)){
					written = true;
				}
			}
			scanner.close();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		
		if(!written){
			Writer writer = null;
			try {
				writer = new FileWriter(path+"\\"+fileName,true);
				writer.write("\nlibrary IEEE;\n");
				writer.write("use IEEE.STD_LOGIC_1164.ALL;\n");
				writer.write("use IEEE.numeric_std.all;\n");
				
				writer.write("\nentity " + VHDLName + " is\n");
				//if(this.inputSize == 1){
				writer.write("port( x0: in std_logic;\n");
				for(int x = 1; x < busSize; x++){
					writer.write("x" + x + ": in std_logic;\n");
				}
				
				writer.write("F: out std_logic\n");	
				
				writer.write(");\n");
				
				writer.write("end "+ VHDLName + ";\n\n");
				
				writer.write("architecture behav of "+ VHDLName + " is\n");
				writer.write("signal x: std_logic_vector(" +(busSize-1) + " downto 0);\n");
				writer.write("begin\n");
				
				for(int x = 0; x < busSize; x++){
					writer.write("x(" + x + ") <= x" + x + ";\n");
				}

				/*writer.write("if "+function+" then\n");
				writer.write("  f <= '1';\n");
				writer.write("else\n");
				writer.write("  f <= '0';\n");
				writer.write("end if;\n");*/
				writer.write("f <= '1' when "+function+" else '0';\n");
				//writer.write(";\n");
				writer.write("end behav;\n");
				
				writer.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
