/**
 * \brief Analyze a single grid point
 *
 * Moves (relatively) to a grid point, takes an image and returns the
 * the offset as measured by the tracker.
 */
Point	CalibrationProcess::starAt(double ra, double dec) {
	// move the telescope to the point
	moveto(grid * ra, grid * dec);

	// take an image at that position
	imager().startExposure(exposure());
	usleep(1000000 * exposure().exposuretime());
	ImagePtr	image = guider().getImage();

	// analze the image
	Point	star = (*tracker())(image);
	debug(LOG_DEBUG, DEBUG_LOG, 0, "tracker found star at %s",
		star.toString().c_str());
	return star;
}
int main(int argc, char *argv[])
{

    namespace po = boost::program_options;
    bool magicPartition;
    unsigned int rounds;
    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ("imageName", po::value<std::string>(), "teasafe image path")
        ("blockCount", po::value<uint64_t>(), "size of filesystem in 4096 blocks (12800 = 50MB)")
        ("coffee", po::value<bool>(&magicPartition)->default_value(false), "create alternative sub-volume")
        ("rounds", po::value<unsigned int>(&rounds)->default_value(64), "number of encryption rounds");

    po::positional_options_description positionalOptions;
    (void)positionalOptions.add("imageName", 1);
    (void)positionalOptions.add("blockCount", 1);

    teasafe::SharedCoreIO io(boost::make_shared<teasafe::CoreTeaSafeIO>());

    // use a non-deterministic random device to generate the iv. This
    // allegedly pulls data from /dev/urandom
    io->iv = teasafe::utility::random();

    po::variables_map vm;
    try {
        po::store(po::command_line_parser(argc, argv).
                  options(desc).positional(positionalOptions).run(),
                  vm);
        po::notify(vm);
        if (vm.count("help") ||
            vm.count("imageName")==0 || vm.count("blockCount") == 0) {
            std::cout << desc << std::endl;
            return 1;
        }

        if (vm.count("help")) {
            std::cout<<desc<<"\n";
        } else {

            if(rounds > 255) {
                std::cout<<"Rounds must be <= 255 (and > 0). By design, the resulting image ";
                std::cout<<"allocates only one byte to storing this value. Note, ";
                std::cout<<"a value of 64 is suggested by the literature to be a 'good' value."<<std::endl;
                return 1;
            }

            std::cout<<"image path: "<<vm["imageName"].as<std::string>()<<std::endl;
            std::cout<<"file system size in blocks: "<<vm["blockCount"].as<uint64_t>()<<std::endl;
            std::cout<<"number of encryption rounds: "<<vm["rounds"].as<unsigned int>()<<std::endl;
            std::cout<<"initialization vector: "<<io->iv<<std::endl;
        }
    } catch (...) {
        std::cout<<"Problem parsing options"<<std::endl;
        std::cout<<desc<<std::endl;
        return 1;
    }

    uint64_t blocks = vm["blockCount"].as<uint64_t>();

    io->path = vm["imageName"].as<std::string>().c_str();
    io->blocks = blocks;
    io->freeBlocks = blocks;
    io->password.append(teasafe::utility::getPassword("teasafe password: "******"sub-volume root block: ").c_str());
        if(partBlock == 0 || partBlock >= blocks) {
            std::cout<<"Error: sub-volume root block must be less than "<<blocks<<" AND greater than 0"<<std::endl;
            return 1;
        }

        omp = teasafe::OptionalMagicPart(partBlock);
    }

    // register progress call back for cipher
    long const amount = teasafe::detail::CIPHER_BUFFER_SIZE / 100000;
    boost::function<void(teasafe::EventType)> f(boost::bind(&teasafe::cipherCallback, _1, amount));
    io->ccb = f;

    teasafe::MakeTeaSafe imager(io, omp);

    // register progress callback for imager
    boost::function<void(teasafe::EventType)> fb(boost::bind(&imagerCallback, _1, io->blocks));
    imager.registerSignalHandler(fb);
    imager.buildImage();

    return 0;
}