#include "fileprocess.h"
#include "fileprocess.grpc.pb.h"
#include <grpc++/server_builder.h>

using namespace std;
using namespace grpc;
using namespace fileprocess;

class FileProcessServer final : public FileProcess::Service {

    handler_fn _handle_image;

    Status ProcessFiles(ServerContext* context, const Files* request,
                        Output *resp) override {
        printf("process files\n");
        for (auto file: request->files()) {
            printf("file: %s\n", file.path().c_str());
            string output_path;
            vector<uint8_t> output;
            vector<uint8_t> input(file.data().begin(), file.data().end());
            auto r = _handle_image(file.path(), input, output_path, output);
            auto d = resp->add_files();
            if (r) {
                d->set_succeeded(false);
                d->set_error("Failed to process image");
            } else {
                d->set_succeeded(true);
                d->set_path(output_path);
                string data(output.begin(), output.end());
                d->set_data(data);
            }
        }
        printf("done\n");
        return Status::OK;
    }

#if 0
    Status ProcessArchive(ServerContext* context, ServerReaderWriter<Output, ArchiveFile> *stream) override {
        ArchiveFile request;
        while (stream->Read(&request)) {
            if (request.data().size() <= 0) continue;
            string output_path;
            vector<uint8_t> output;
            vector<uint8_t> input(request.data().begin(), request.data().end());
            string path = request.path();
            path += string("-files/") + request.path_in_archive();
            auto r = _handle_image(path, input, output_path, output);
            Output d;
            if (r) {
                d.set_succeeded(false);
                string error = "Failed to process image " + request.path_in_archive();
                d.set_error(error);
            } else {
                d.set_succeeded(true);
                d.set_path(output_path);
                string data(output.begin(), output.end());
                d.set_data(data);
            }
            stream->Write(d);
        }
        return Status::OK;
    }
#endif

public:
    FileProcessServer(handler_fn handle_image) :
        _handle_image(handle_image)
    {
    }
};

int run_server(const string &server_addr, handler_fn handle_image) {
  FileProcessServer service(handle_image);

  ServerBuilder builder;
  builder.AddListeningPort(server_addr, grpc::InsecureServerCredentials());
  builder.RegisterService(&service);
  builder.SetMaxSendMessageSize(128 * 1024 * 1024);
  std::unique_ptr<Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_addr << std::endl;
  server->Wait();
  return 0;
}

