/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This sample progam demonstrates how to use Skia and HarfBuzz to
// produce a PDF file from UTF-8 text in stdin.

#include <cassert>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <sstream>

#include <hb-ot.h>

#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkStream.h"
#include "SkTextBlob.h"
#include "SkTypeface.h"

struct BaseOption {
  std::string selector;
  std::string description;
  virtual void set(std::string _value) = 0;
  virtual std::string valueToString() = 0;

  BaseOption(std::string _selector, std::string _description) :
    selector(_selector),
    description(_description) {}

  virtual ~BaseOption() {}
};

template <class T> struct Option : BaseOption {
  T value;
  Option(std::string selector, std::string description, T defaultValue) :
    BaseOption(selector, description),
    value(defaultValue) {}
};

struct DoubleOption : Option<double> {
  virtual void set(std::string _value) {
    value = atof(_value.c_str());
  }
  virtual std::string valueToString() {
      std::ostringstream stm;
      stm << value;
      return stm.str();
  }
  DoubleOption(std::string selector, std::string description, double defaultValue) :
    Option<double>(selector, description, defaultValue) {}
};

struct SkStringOption : Option<SkString> {
  virtual void set(std::string _value) {
    value = _value.c_str();
  }
  virtual std::string valueToString() {
    return value.c_str();
  }
  SkStringOption(std::string selector, std::string description, SkString defaultValue) :
    Option<SkString>(selector, description, defaultValue) {}
};

struct StdStringOption : Option<std::string> {
  virtual void set(std::string _value) {
    value = _value;
  }
  virtual std::string valueToString() {
    return value;
  }
  StdStringOption(std::string selector, std::string description, std::string defaultValue) :
    Option<std::string>(selector, description, defaultValue) {}
};

struct Config {
  DoubleOption *page_width = new DoubleOption("-w", "Page width", 600.0f);
  DoubleOption *page_height = new DoubleOption("-h", "Page height", 800.0f);
  SkStringOption *title = new SkStringOption("-t", "PDF title", SkString("---"));
  SkStringOption *author = new SkStringOption("-a", "PDF author", SkString("---"));
  SkStringOption *subject = new SkStringOption("-k", "PDF subject", SkString("---"));
  SkStringOption *keywords = new SkStringOption("-c", "PDF keywords", SkString("---"));
  SkStringOption *creator = new SkStringOption("-t", "PDF creator", SkString("---"));
  StdStringOption *font_file = new StdStringOption("-f", ".ttf font file", "");
  DoubleOption *font_size = new DoubleOption("-z", "Font size", 8.0f);
  DoubleOption *left_margin = new DoubleOption("-m", "Left margin", 20.0f);
  DoubleOption *line_spacing_ratio = new DoubleOption("-h", "Line spacing ratio", 1.5f);
  StdStringOption *output_file_name = new StdStringOption("-o", ".pdf output file name", "out-skiahf.pdf");

  std::map<std::string, BaseOption*> options = {
    { page_width->selector, page_width },
    { page_height->selector, page_height },
    { title->selector, title },
    { author->selector, author },
    { subject->selector, subject },
    { keywords->selector, keywords },
    { creator->selector, creator },
    { font_file->selector, font_file },
    { font_size->selector, font_size },
    { left_margin->selector, left_margin },
    { line_spacing_ratio->selector, line_spacing_ratio },
    { output_file_name->selector, output_file_name },
  };

  Config(int argc, char **argv) {
    for (int i = 1; i < argc; i++) {
      std::string option_selector(argv[i]);
      auto it = options.find(option_selector);
      if (it != options.end()) {
        if (i >= argc) {
          break;
        }
        const char *option_value = argv[i + 1];
        it->second->set(option_value);
        i++;
      } else {
        printf("Ignoring unrecognized option: %s.\n", argv[i]);
        printf("Usage: %s {option value}\n", argv[0]);
        printf("\tTakes text from stdin and produces pdf file.\n");
        printf("Supported options:\n");
        for (auto it = options.begin(); it != options.end(); ++it) {
          printf("\t%s\t%s (%s)\n", it->first.c_str(),
            it->second->description.c_str(),
            it->second->valueToString().c_str());
        }
        exit(-1);
      }
    }
  } // end of Config::Config
};

const double FONT_SIZE_SCALE = 64.0f;

struct Face {
  struct HBFDel { void operator()(hb_face_t* f) { hb_face_destroy(f); } };
  std::unique_ptr<hb_face_t, HBFDel> fHarfBuzzFace;
  sk_sp<SkTypeface> fSkiaTypeface;

  Face(sk_sp<SkTypeface> skiaTypeface) : fSkiaTypeface(std::move(skiaTypeface)) {
    int index;
    std::unique_ptr<SkStreamAsset> asset(fSkiaTypeface->openStream(&index));
    size_t size = asset->getLength();
    // TODO(halcanary): avoid this malloc and copy.
    char* buffer = (char*)malloc(size);
    asset->read(buffer, size);
    hb_blob_t* blob = hb_blob_create(buffer,
                                     size,
                                     HB_MEMORY_MODE_READONLY,
                                     nullptr,
                                     free);
    assert(blob);
    hb_blob_make_immutable(blob);
    hb_face_t* face = hb_face_create(blob, (unsigned)index);
    hb_blob_destroy(blob);
    assert(face);
    if (!face) {
        fSkiaTypeface.reset();
        return;
    }
    hb_face_set_index(face, (unsigned)index);
    hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm());
    fHarfBuzzFace.reset(face);
  }
  Face(const char* path, int index) {
    // fairly portable mmap impl
    auto data = SkData::MakeFromFileName(path);
    assert(data);
    if (!data) { return; }
    fSkiaTypeface = SkTypeface::MakeFromStream(new SkMemoryStream(data), index);
    assert(fSkiaTypeface);
    if (!fSkiaTypeface) { return; }
    auto destroy = [](void *d) { static_cast<SkData*>(d)->unref(); };
    const char* bytes = (const char*)data->data();
    unsigned int size = (unsigned int)data->size();
    hb_blob_t* blob = hb_blob_create(bytes,
                                     size,
                                     HB_MEMORY_MODE_READONLY,
                                     data.release(),
                                     destroy);
    assert(blob);
    hb_blob_make_immutable(blob);
    hb_face_t* face = hb_face_create(blob, (unsigned)index);
    hb_blob_destroy(blob);
    assert(face);
    if (!face) {
        fSkiaTypeface.reset();
        return;
    }
    hb_face_set_index(face, (unsigned)index);
    hb_face_set_upem(face, fSkiaTypeface->getUnitsPerEm());
    fHarfBuzzFace.reset(face);
  }
};

class Placement {
 public:
  Placement(Config &_config, SkWStream* outputStream) : config(_config) {
    const std::string& font_file = config.font_file->value;
    if (font_file.size() > 0) {
      face = new Face(font_file.c_str(), 0 /* index */);
    } else {
      face = new Face(SkTypeface::MakeDefault());
    }
    hb_font = hb_font_create(face->fHarfBuzzFace.get());

    hb_font_set_scale(hb_font,
        FONT_SIZE_SCALE * config.font_size->value,
        FONT_SIZE_SCALE * config.font_size->value);
    hb_ot_font_set_funcs(hb_font);

    SkDocument::PDFMetadata pdf_info;
    pdf_info.fTitle = config.title->value;
    pdf_info.fAuthor = config.author->value;
    pdf_info.fSubject = config.subject->value;
    pdf_info.fKeywords = config.keywords->value;
    pdf_info.fCreator = config.creator->value;
    SkTime::DateTime now;
    SkTime::GetDateTime(&now);
    pdf_info.fCreation.fEnabled = true;
    pdf_info.fCreation.fDateTime = now;
    pdf_info.fModified.fEnabled = true;
    pdf_info.fModified.fDateTime = now;
    pdfDocument = SkDocument::MakePDF(outputStream, SK_ScalarDefaultRasterDPI,
                                      pdf_info, nullptr, true);
    assert(pdfDocument);

    white_paint.setColor(SK_ColorWHITE);

    glyph_paint.setFlags(
        SkPaint::kAntiAlias_Flag |
        SkPaint::kSubpixelText_Flag);  // ... avoid waggly text when rotating.
    glyph_paint.setColor(SK_ColorBLACK);
    glyph_paint.setTextSize(config.font_size->value);
    glyph_paint.setTypeface(face->fSkiaTypeface);
    glyph_paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    NewPage();
  } // end of Placement

  ~Placement() {
    delete face;
    hb_font_destroy (hb_font);
  }

  void WriteLine(const char *text) {
    /* Create hb-buffer and populate. */
    hb_buffer_t *hb_buffer = hb_buffer_create ();
    hb_buffer_add_utf8 (hb_buffer, text, -1, 0, -1);
    hb_buffer_guess_segment_properties (hb_buffer);

    /* Shape it! */
    hb_shape (hb_font, hb_buffer, NULL, 0);

    DrawGlyphs(hb_buffer);

    hb_buffer_destroy (hb_buffer);

    // Advance to the next line.
    current_y += config.line_spacing_ratio->value * config.font_size->value;
    if (current_y > config.page_height->value) {
      pdfDocument->endPage();
      NewPage();
    }
  }

  bool Close() {
    return pdfDocument->close();
  }

private:
  Config config;

  Face *face;

  hb_font_t *hb_font;

  sk_sp<SkDocument> pdfDocument;

  SkCanvas* pageCanvas;

  SkPaint white_paint;
  SkPaint glyph_paint;

  double current_x;
  double current_y;

  void NewPage() {
    pageCanvas = pdfDocument->beginPage(config.page_width->value, config.page_height->value);

    pageCanvas->drawPaint(white_paint);

    current_x = config.left_margin->value;
    current_y = config.line_spacing_ratio->value * config.font_size->value;
  }

  bool DrawGlyphs(hb_buffer_t *hb_buffer) {
    SkTextBlobBuilder textBlobBuilder;
    unsigned len = hb_buffer_get_length (hb_buffer);
    if (len == 0) {
      return true;
    }
    hb_glyph_info_t *info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
    hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
    auto runBuffer = textBlobBuilder.allocRunPos(glyph_paint, len);

    double x = 0;
    double y = 0;
    for (unsigned int i = 0; i < len; i++)
    {
      runBuffer.glyphs[i] = info[i].codepoint;
      reinterpret_cast<SkPoint*>(runBuffer.pos)[i] = SkPoint::Make(
        x + pos[i].x_offset / FONT_SIZE_SCALE,
        y - pos[i].y_offset / FONT_SIZE_SCALE);
      x += pos[i].x_advance / FONT_SIZE_SCALE;
      y += pos[i].y_advance / FONT_SIZE_SCALE;
    }

    pageCanvas->drawTextBlob(textBlobBuilder.build(), current_x, current_y, glyph_paint);
    return true;
  } // end of DrawGlyphs
}; // end of Placement class

int main(int argc, char** argv) {
    Config config(argc, argv);

    Placement placement(config, new SkFILEWStream(config.output_file_name->value.c_str()));
    for (std::string line; std::getline(std::cin, line);) {
      placement.WriteLine(line.c_str());
    }
    placement.Close();

    return 0;
}
