/* Copyright 2017-present Renesas Electronics Corporation and other contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

#define NAME_STRINGIZER_(name) #name
#define NAME_STRINGIZER(name) NAME_STRINGIZER_(name)

#include "mbed.h"
#include "iotjs.h"

// git clone https://github.com/ARMmbed/sd-driver.git
#include "FATFileSystem.h"
#include "SDBlockDevice.h"

namespace {

	#if defined(SD_MOUNT_NAME)
		const std::string mount_name_ = NAME_STRINGIZER(SD_MOUNT_NAME);
	#else
		const std::string mount_name_ = "sd";
	#endif

	bool by_file( std::string& fullpath )
	{
		fullpath.clear();
		std::cout << std::endl << "input js fullpath here: ";
		std::string path;
		std::getline( std::cin, path );
		path.erase( std::remove( path.begin(), path.end(), '\r' ), path.end() );
		if( path.empty() || path[ path.size() - 1 ] == '!' ) {	// quit
			return false;
		}
		if( path[ path.size() - 1 ] == '@' ) {	// re-try
			return true;
		}
		fullpath = path;
		return false;
	}

	bool by_code( std::string& fullpath )
	{
		fullpath.clear();
		std::cout << std::endl << "input javascript code here: ";
		std::string code;
		while( true ) {
			std::string line;
			std::getline( std::cin, line );
			line.erase( std::remove( line.begin(), line.end(), '\r' ), line.end() );
			code += line + "\n";
			if( line.empty() ) {	// ignore
				;
			}
			else if( line[ line.size() - 1 ] == '!' ) {	// quit
				return false;
			}
			else if( line[ line.size() - 1 ] == '@' ) {	// re-try
				return true;
			}
			else if( line.find("//eoc") != std::string::npos ) {
				break;
			}
		}

		fullpath = "/" + mount_name_ + "/_temp_code.js";
		std::ofstream ofs( fullpath.c_str() );
		ofs << code;
		return false;
	}

	void iotjs_main()
	{
		printf("IoT.js for mbed-os...\n");
		printf("   mbed-os version: %d.%d.%d \n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
		printf("   build timestamp: " __DATE__ " " __TIME__ " \n");

		std::string path;
		for(;;) {
			while( by_file( path ) ); if( !path.empty() ) break;
			while( by_code( path ) ); if( !path.empty() ) break;
	///		while( by_http( path ) ); if( !path.empty() ) break;
		}

		int ac = 2;
		const char* av[] = {"iotjs", &path[0], 0};
		iotjs_entry(ac, (char**)av);
	}

}	// namespace file-local

int main()
{
	Serial pc( USBTX, USBRX );
	pc.baud( 115200 );

	SDBlockDevice bd( P8_5, P8_6, P8_3, P8_4 );
	FATFileSystem fs( mount_name_.c_str() );
	int error = fs.mount( &bd ); (void)error;	// Mounting the filesystem on /<mount_name>

	const uint32_t stack_size = 32 * 1024;
	Thread iotjsThread( osPriorityNormal, stack_size );
	iotjsThread.start( callback( iotjs_main ) );
	iotjsThread.join();

	std::cout << "bye!" << std::endl;
	return 0;
}

