/***********************************************************************
 * This file is part of Adempiere ERP Bazaar                           *
 * http://www.adempiere.org                                            *
 *                                                                     *
 * Copyright (C) Fernando Lucktemberg - fer_luck                       *
 * Copyright (C) Contributors                                          *
 *                                                                     *
 * This program is free software; you can redistribute it and/or       *
 * modify it under the terms of the GNU General Public License         *
 * as published by the Free Software Foundation; either version 2      *
 * of the License, or (at your option) any later version.              *
 *                                                                     *
 * This program is distributed in the hope that it will be useful,     *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the        *
 * GNU General Public License for more details.                        *
 *                                                                     *
 * You should have received a copy of the GNU General Public License   *
 * along with this program; if not, write to the Free Software         *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,          *
 * MA 02110-1301, USA.                                                 *
 *                                                                     *
 * Contributors:                                                       *
 * - Fernando Lucktemberg - fer_luck                                   *
 *                                                                     *
 * Sponsors:                                                           *
 * - Company (http://www.faire.com.br)                                 *
 **********************************************************************/

package org.adempiere.process;

import java.io.File;
import java.io.FilenameFilter;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Scanner;
import java.util.logging.Level;

import org.compiere.Adempiere;
import org.compiere.model.MProcessPara;
import org.compiere.process.ProcessInfoParameter;
import org.compiere.process.SvrProcess;
import org.compiere.util.DB;
import org.compiere.util.Env;

@org.adempiere.base.annotation.Process
public class PrepareMigrationScripts extends SvrProcess {

	String path;

	// Charset found variable
	public static boolean found = false;

	@Override
	protected String doIt() throws Exception {
		String directory;
		if (path != null)
			directory = path;
		else
			return "ERROR - No path";
		File dir = new File(directory);

		// The list of files can also be retrieved as File objects
		File[] dirList = dir.listFiles();
		ArrayList<String> fileName = new ArrayList<String>();

		FilenameFilter filter = new FilenameFilter() {
			public boolean accept(File dir, String name) {
				return name.toLowerCase().endsWith(".sql");
			}
		};
		dirList = dir.listFiles(filter);

		StringBuilder msglog = new StringBuilder("Searching for SQL files in the ").append(dir).append(" directory");
		if (log.isLoggable(Level.INFO)) log.info(msglog.toString());

		StringBuilder msg = new StringBuilder();

		// Get Filenames
		for (int i = 0; i < dirList.length; i++) {
			fileName.add(dirList[i].toString()
					.substring(directory.length() + 1));
			msglog = new StringBuilder("Found file [")
							.append(fileName.get(i))
							.append("]. Finding out if the script has or hasn't been applied yet...");
			log.fine(msglog.toString());
			PreparedStatement pstmt = null;
			ResultSet rs = null;
			try {
				// First of all, check if the script hasn't been applied yet...
				String checkScript = "select ad_migrationscript_id from ad_migrationscript where name = ?";
				pstmt = DB.prepareStatement(checkScript, this
						.get_TrxName());
				pstmt.setString(1, fileName.get(i));
				rs = pstmt.executeQuery();
				if (rs.next()) {
					msglog = new StringBuilder("Script ").append(fileName.get(i))
							.append(" already in the database");
					log.warning(msglog.toString());
					continue;
				}
				DB.close(pstmt);
				pstmt = null;
				// first use a Scanner to get each line
				Scanner scanner = new Scanner(dirList[i]);
				StringBuilder body = new StringBuilder();
				boolean blHeader = false;
				boolean blBody = false;
				boolean isFirstLine = true;
				boolean hasHeader = false;
				String Name = fileName.get(i);
				String Description = "Unknown";
				String ProjectName = "Adempiere";
				String tmp = Adempiere.MAIN_VERSION;
				tmp = tmp.replace("Release ", "");
				tmp = tmp.replace(".", "");
				String ReleaseNo = tmp;
				String DeveloperName = "Not known";
				String Reference = "--";
				String Url = "http://www.sourceforge.net/projects/adempiere";
				Timestamp ts = new Timestamp(Calendar.getInstance()
						.getTimeInMillis());
				while (scanner.hasNextLine()) {
					String line = null;
					// if it's the first line check for the header
					if (isFirstLine)
						line = scanner.nextLine();
					if (isFirstLine && line.equals("--BEGINHEADER--"))
						hasHeader = true;
					if (hasHeader) {
						if (!isFirstLine)
							line = scanner.nextLine();
						if (line.equals("--ENDHEADER--")) {
							blHeader = false;
							blBody = false;
						}
						if (line.equals("--ENDMS--")) {
							blHeader = false;
							blBody = false;
						}
						if (blHeader) {
							if (line.startsWith("Name")) {
								Name = line.substring("Name".length() + 1);
							} else if (line.startsWith("Description")) {
								Description = line.substring("Description"
										.length() + 1);
							} else if (line.startsWith("ProjectName")) {
								ProjectName = line.substring("ProjectName"
										.length() + 1);
							} else if (line.startsWith("ReleaseNo")) {
								ReleaseNo = line
										.substring("ReleaseNo".length() + 1);
							} else if (line.startsWith("DeveloperName")) {
								DeveloperName = line.substring("DeveloperName"
										.length() + 1);
							} else if (line.startsWith("Reference")) {
								Reference = line
										.substring("Reference".length() + 1);
							} else if (line.startsWith("Url")) {
								Url = line.substring("Url".length() + 1);
							}
						}
						if (blBody) {
							body.append(line).append('\n');
						}
						if (line.equals("--BEGINHEADER--")) {
							blHeader = true;
							blBody = false;
						}
						if (line.equals("--BEGINMS--")) {
							blHeader = false;
							blBody = true;
						}
					} else {
						if (!isFirstLine)
							line = scanner.nextLine();
						body.append(line).append('\n');
					}
					isFirstLine = false;
				}
				scanner.close();
				int seqID = DB.getNextID(0, "AD_MigrationScript", this
						.get_TrxName());
				String sql = "INSERT INTO ad_migrationscript (ad_client_id, ad_org_id, "
						+ "ad_migrationscript_id,  createdby, "
						+ "name, projectname, "
						+ "releaseno, status, "
						+ "url, updatedby, "
						+ "filename, description, "
						+ "developername, reference, "
						+ "isactive, isapply, "
						+ "created, updated) "
						+ "VALUES "
						+ "(0, 0, ?, ?, "
						+ "?, ?, ?, ?, "
						+ "?, ?, ?, ?, "
						+ "?, ?, ?, ?, "
						+ "?, ? )";
				pstmt = DB.prepareStatement(sql, this.get_TrxName());
				pstmt.setInt(1, seqID);
				pstmt.setInt(2, Env.getAD_User_ID(Env.getCtx()));
				pstmt.setString(3, Name);
				pstmt.setString(4, ProjectName);
				pstmt.setString(5, ReleaseNo);
				pstmt.setString(6, "IP");
				pstmt.setString(7, Url);
				pstmt.setInt(8, Env.getAD_User_ID(Env.getCtx()));
				pstmt.setString(9, path);
				pstmt.setString(10, Description);
				pstmt.setString(11, DeveloperName);
				pstmt.setString(12, Reference);
				pstmt.setString(13, "Y");
				pstmt.setString(14, "Y");
				pstmt.setTimestamp(15, ts);
				pstmt.setTimestamp(16, ts);
				int result = pstmt.executeUpdate();
				DB.close(pstmt);
				pstmt = null;
				if (result > 0)
					log.info("Header inserted. Now inserting the script body");
				else {
					msglog = new StringBuilder("Script ").append(fileName.get(i)).append(" failed!");
					log.severe(msglog.toString());
					msg.append(msglog);
					continue;
				}
				sql = "UPDATE AD_MigrationScript SET script = ? WHERE AD_MigrationScript_ID = ?";
				pstmt = DB.prepareStatement(sql, this.get_TrxName());
				pstmt.setBytes(1, body.toString().getBytes());
				pstmt.setInt(2, seqID);
				result = pstmt.executeUpdate();
				DB.close(pstmt);
				pstmt = null;
				if (result > 0)
					log.info("Script Body inserted.");
				else {
					msglog = new StringBuilder("Script Body ").append(fileName.get(i)).append(" failed!");
					log.severe(msglog.toString());
					msg.append(msglog.toString());
					pstmt = DB
							.prepareStatement(
									"DELETE FROM ad_migrationscript WHERE ad_migrationscript_id = ?",
									this.get_TrxName());
					pstmt.setInt(1, seqID);
					result = pstmt.executeUpdate();
					continue;
				}
			} catch (Exception ex) {
				log.severe(ex.getMessage());
			}
			finally
			{
				DB.close(rs, pstmt);
				rs = null;
				pstmt = null;
			}
			
		}
		return "Success";
	}

	@Override
	protected void prepare() {
		ProcessInfoParameter[] para = getParameter();
		for (int i = 0; i < para.length; i++) {
			String name = para[i].getParameterName();
			if (para[i].getParameter() == null)
				;
			else if (name.equals("ScriptsPath"))
				path = (String) para[i].getParameter();
			else
				MProcessPara.validateUnknownParameter(getProcessInfo().getAD_Process_ID(), para[i]);
		}

	}
}
