/*-------------------------------------------------------------------------------
  convertdata.ado: (batch) convert datasets using the external tool Stat/Transfer

    Copyright (C) 2010-2012  Daniel Bela (daniel.bela@lifbi.de)

    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 3 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, see <http://www.gnu.org/licenses/>.

-------------------------------------------------------------------------------*/
*! convertdata.ado: (batch) convert datasets using the external tool Stat/Transfer
*! Daniel Bela (daniel.bela@lifbi.de), Leibniz Institute for Educational Trajectories (LIfBi), Germany
*! version 1.1 06 Match 2012 - updated standard file paths for Stat/Transfer 11
*! version 1.0 22 December 2010 - initial release
program define convertdata, nclass
	version 11.1
	syntax , FROMextension(string) TOextension(string) [INputdirectory(string) OUTputdirectory(string) MKOUTputdirectory COMmand(string) REPLACE FILENAME(string)]
	preserve
	local workdir `"`c(pwd)'"'		// save current directory
	// set `inputdirectory' to working directory if empty:
	if "`inputdirectory'"=="" {
		local inputdirectory `"`workdir'"'
	}

	// verify `inputdirectory' to be a valid directory and set to working directory if not:
	if `"`inputdirectory'"'!=`"`workdir'"' {
		capture: cd `"`inputdirectory'"'
		quietly: cd `"`workdir'"'		// restore directory
		if `c(rc)'!=0 {
			noisily: display as error `"Your input "`inputdirectory'" does not seem to be a "'
			noisily: display as error `"valid directory or is not accessible. Using working directory instead."'
			local inputdirectory `"`workdir'"'
		}
	}

	// set `outputdirectory' to working directory if empty:
	if "`outputdirectory'"=="" {
		local outputdirectory `"`workdir'"'
	}

	// create `outputdirectory' if requested and possible:
	if "`mkoutputdirectory'"=="mkoutputdirectory" {
		capture: cd `"`outputdirectory'"'
		quietly: cd `"`workdir'"'		// restore directory
		if `c(rc)'==0 {
			noisily: display as text `"Directory "`outputdirectory'" already exists."'
			noisily: display as text `"Skipping creation of directory as requested."'
		}
		else {
			capture: mkdir `"`outputdirectory'"'
			if `c(rc)'!=0 {
				noisily: display as error `"Your input directory "`outputdirectory'""'
				noisily: display as error `"could not be created as requested. Aborting."'
				error `c(rc)'
				exit
			}
		}
	}
	// verify `outputdirectory' to be a valid directory and set to working directory if not:
	else {
		capture: cd `"`outputdirectory'"'
		quietly: cd `"`workdir'"'		// restore directory
		if `c(rc)'!=0 {
			noisily: display as error `"Your input "`outputdirectory'" does not seem to be a "'
			noisily: display as error `"valid directory or is not accessible. Using working directory instead."'
			local outputdirectory `"`workdir'"'
		}
	}

	// set `command' to standard installation path if empty:
	if "`command'"=="" {
		if "`c(os)'"=="Windows" {
			// Windows only: use %PROGRAMFILES% to query installation path:
			local winprogs: environment PROGRAMFILES
			local winprogs: subinstr local winprogs "\" "/", all
			// special case: x64-Windows needs the addition " (x86)" behind %PROGRAMFILES%:
			if "`c(osdtl)'"=="64-bit" {
				local winprogs86 `"`winprogs' (x86)"'
			}
			local command "`winprogs86'`c(dirsep)'StatTransfer11`c(dirsep)'st.exe"
		}
		else if "`c(os)'"=="Unix" {
			local command "`c(dirsep)'usr`c(dirsep)'local`c(dirsep)'stattransfer11`c(dirsep)'st"
		}
		else if "`c(os)'"=="MacOSX" {
			local command "`c(dirsep)'Applications`c(dirsep)'StatTransfer11`c(dirsep)'StatTransfer.app`c(dirsep)'Contents`c(dirsep)'MacOS`c(dirsep)'st"
		}
		else {
			noisily: display as error `"Operating system could not be determined. Please specify"'
			noisily: display as error `"your Stat/Transfer terminal command using the option "command()"."'
			error 198
			exit
		}
	}
	capture: confirm file `"`command'"'		// verify that `command' exists and is accessible
	if _rc!=0 & "`c(os)'"=="Windows" & "`c(osdtl)'"=="64-bit" {
		local command "`winprogs'`c(dirsep)'StatTransfer11-64`c(dirsep)'st.exe"
		confirm file `"`command'"'
	}
	else if _rc!=0 confirm file `"`command'"'
	noisily: display as text `"Running dataset conversion from <.`fromextension'> to <.`toextension'>"'
	noisily: display as text `"from directory "`inputdirectory'" to "`outputdirectory'""'
	noisily: display as text `"(using Stat/Transfer terminal command "`command'")."'

	// run procedure:
	if `"`filename'"'!="" {
		local filename=regexr("`filename'","\.[a-z,A-Z,0-9]*$","")		// remove file extension if necessary
		local source `"`inputdirectory'`c(dirsep)'`filename'.`fromextension'"'
		local destination `"`outputdirectory'`c(dirsep)'`filename'.`toextension'"'
		display as text `"<`filename'.`fromextension'> ---> <`filename'.`toextension'>..."'
		capture: confirm file `"`source'"' // verify input file exists
		if `c(rc)'!=0 {
			noisily: display as error `"File <`source'> not found."'
			noisily: display as error `"File conversion aborted."'
			error `c(rc)'
			exit
		}
		if "`replace'"=="replace" {
			capture: erase "`destination'"
		}
		capture: confirm new file `"`destination'"'
		if `c(rc)'==602 {
			noisily: display as text `"<`filename'.`toextension'> already exists. Skipped"'
		}
		else {
			capture: removeSTprofile		// subroutine defined below
			generateSTprofile		// subroutine defined below
			quietly: cd `"`c(tmpdir)'"'		// run Stat/Transfer from <tmpdir> using the new <profile.stcmd>
			quietly: shell "`command'" "`source'" "`destination'"
			removeSTprofile		// subroutine defined below
		}
		noisily: display as result `"...done."'
		quietly: cd `"`workdir'"'
		noisily: display as result _newline `"File conversion operation finished."'
	}
	else {
		quietly: retrievefilenames, filedirectory(`inputdirectory') extension(`fromextension') strip
		if `"`r(filenames)'"'=="" {
			noisily: display as error `"No file with extension <`fromextension'> found."'
			noisily: display as error `"File conversion aborted."'
			error 601
			exit
		}
		local filenames `"`r(filenames)'"'
		capture: removeSTprofile		// subroutine defined below
		generateSTprofile		// subroutine defined below
		quietly: cd `"`c(tmpdir)'"'		// run Stat/Transfer from <tmpdir> using the new <profile.stcmd>
		foreach file of local filenames {
			local source `"`inputdirectory'`c(dirsep)'`file'.`fromextension'"'
			local destination `"`outputdirectory'`c(dirsep)'`file'.`toextension'"'
			display as text `"<`file'.`fromextension'> ---> <`file'.`toextension'>..."'
			if "`replace'"=="replace" {
				capture: erase "`destination'"
			}
			capture: confirm new file `"`destination'"'
			if `c(rc)'==602 {
				noisily: display as text `"<`file'.`toextension'> already exists. Skipped"'
			}
			else {
				quietly: shell "`command'" "`source'" "`destination'"
			}
			noisily: display as result `"...done."'_newline
		}
		removeSTprofile		// subroutine defined below
		quietly: cd `"`workdir'"'
		noisily: display as result _newline `"File conversion operations finished."'
	}
end

// subroutine: generate Stat/Transfer configuration file:
program define generateSTprofile
	quietly: file open STprofile using `"`c(tmpdir)'profile.stcmd"', write text replace
	#delimit ;
	noisily: file write STprofile
		"//ENCODING UTF-8"_newline
		"set numeric-names N"_newline
		"set log-level e"_newline
		"set in-encoding system"_newline
		"set out-encoding system"_newline
		"set enc-errors sub"_newline
		"set enc-sub-char _"_newline
		"set enc-error-limit -1"_newline
		"set var-case-cs preserve-mixed"_newline
		"set preserve-label-sets Y"_newline
		"set map-miss-with-labs N"_newline
		"set user-miss none"_newline
		"set map-user-miss N"_newline
		`"set date-fmt-write "%m/%d/%Y""'_newline
		`"set time-fmt-write "%0H:%0M:%0S""'_newline
		`"set datetime-fmt-write "%m/%d/%Y %0H:%0M:%0S""'_newline
		"set num-miss-wr none"_newline
		"set write-old-ver N"_newline;
	#delimit cr
	file close STprofile
end

// subroutine: remove Stat/Transfer configuration file:
program define removeSTprofile
	erase `"`c(tmpdir)'profile.stcmd"'
end
// EOF