#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

template< class T >
inline
string 
to_string(const T & val)
{
   stringstream ss;
   ss << val;
   string str;
   ss >> str;
   return str;
}

namespace pcos {

class Install {
public:
    enum { SIZE = 512 };
    enum { OS_SIZE = 512 };

private:
    char bootloader[SIZE];
    char filetable[SIZE];
    char os[OS_SIZE];
    char temp[SIZE];

    void load(char * buffer, const char * filename, int max) {
       fstream fin(filename, ios::in | ios::binary);
       if(!fin.fail()) {
          fin.seekg(0L, ios::end);
          int size = (int)fin.tellg();
          fin.seekg(0L, ios::beg);
          memset(buffer, 0, max);
          fin.read(buffer, size); 
          fin.close();
       }
       else {
          throw "Unable to load input file...";
       }
    }

public:
    void run(int argc, char ** argv) {
       string fat = "{";
       int off = 3;
       for(int i = 1; i < argc; i++, off++) {
          fat += string(argv[i]) + string("-") + to_string(off) + string(",");
       }
       fat += "}";
cout << "---FAT---" << endl;
cout << fat << endl;
cout << "---------" << endl;
       fstream file("disk.img", ios::in | ios::out | ios::trunc | ios::ate | ios::binary);
       if(!file.fail()) {
          load(bootloader, "bootloader", SIZE);
          load(os, "os", OS_SIZE);
          memset(filetable, 0, SIZE);
          strcpy(filetable, fat.c_str());
          file.write(bootloader, SIZE);
          file.flush();
          file.write(filetable, SIZE);
          file.flush();
          file.write(os, OS_SIZE);
          file.flush();
          for(int i = 2; i < argc; i++) { 
             load(temp, argv[i], SIZE);
             file.write(temp, SIZE);
             file.flush();
          }
          file.close();
       }
       else {
          throw "Unable to open disk image file...";
       }
    }
};

}

int
main(int argc, char ** argv)
{
   int rc = 0;
   try {
      pcos::Install inst;
      inst.run(argc, argv);
   }
   catch(const char * message) {
      cerr << "exception: " << message << endl;
      rc = -1;
   }
   catch(...) {
      cerr << "exception: unknown..." << endl;
      rc = -1;
   }
   return rc;
}
