#include "CiftiFile.h"

#include <iostream>
#include <vector>

using namespace std;
using namespace cifti;

/**\file rewrite.cxx
This program reads a Cifti file from argv[1], and writes it out to argv[2] with a second CiftiFile object.
It uses on-disk reading and writing, so DO NOT have both filenames point to the same file,
CiftiFile truncates without any warning when told to write to an existing file.

\include rewrite.cxx
*/

int main(int argc, char** argv)
{
    if (argc < 3)
    {
        cout << "usage: " << argv[0] << " <input cifti> <output cifti> [<endian>]" << endl;
        cout << "  rewrite the input cifti file to the output filename." << endl;
        cout << "  endian can be 'LITTLE' or 'BIG', and uses native endianness if not specified" << endl;
        return 1;
    }
    CiftiFile::ENDIAN myEndian = CiftiFile::NATIVE;
    if (argc > 3)
    {
        if (AString(argv[3]) == "LITTLE")
        {
            myEndian = CiftiFile::LITTLE;
        } else if (AString(argv[3]) == "BIG") {
            myEndian = CiftiFile::BIG;
        } else {
            cerr << "unrecognized endianness string: " << argv[3] << endl;
            return 1;
        }
    }
    try
    {
        CiftiFile inputFile(argv[1]);//on-disk reading by default
        //inputFile.convertToInMemory();//if you want to read it into memory first
        CiftiFile outputFile;
        outputFile.setWritingFile(argv[2], CiftiVersion(), myEndian);//sets up on-disk writing with default writing version, from CiftiVersion's default constructor
        outputFile.setCiftiXML(inputFile.getCiftiXML());//the CiftiXML is how you access all the mapping information
        const vector<int64_t>& dims = inputFile.getDimensions();
        vector<float> scratchRow(dims[0]);//read/write a row at a time
        for (MultiDimIterator<int64_t> iter = inputFile.getIteratorOverRows(); !iter.atEnd(); ++iter)
        {//helper class to iterate over 2D and 3D cifti with the same code - the "+ 1" is to drop the first dimension (row length)
            inputFile.getRow(scratchRow.data(), *iter);
            outputFile.setRow(scratchRow.data(), *iter);
        }
        outputFile.writeFile(argv[2]);//because we called setWritingFile with this filename (and default cifti version), this will return immediately
        //NOTE: if you call writeFile with a different writing version (takes its default from CiftiVersion constructor) than setWritingFile, it will rewrite the entire file after reading it into memory
        //it will also rewrite it if you specify an endianness other than ANY (which is the default), and the endianness doesn't match what it was already written as (via setWritingFile)
    } catch (CiftiException& e) {
        cerr << "Caught CiftiException: " + AString_to_std_string(e.whatString()) << endl;
        return 1;
    }
    return 0;
}
