/// <reference path="Measure.js"/>
/// <reference path="MarginMeasure.js"/>
/// <reference path="PhantomOutput.js"/>
/// <reference path="PhantomPdfRenderer.js"/>

global.PhantomPdfGenerator = function PhantomPdfGenerator(console, stdin, pageFactory) {
    this._console = console;
    this._stdin = stdin;
    this._pageFactory = pageFactory;
}

PhantomPdfGenerator.prototype = {
    waitForInputThenGenerate: function () {
        if (!this._page) {
            this._page = this._createPage();
            var self = this;
            this._page.onError = function (error, trace) {
                self.onError(error, trace);
            };
            this._page.onConsoleMessage = function (message) {
                self.onMessage(message);
            };
            this._initializePageAndWait();
            return;
        }

        var input = this._stdin.readLine();
        if (input.length > 0) {
            var printInformation = JSON.parse(input);
            if(printInformation.dataFile){ // used when Debug manually.
                var fs = require('fs');
                input = fs.read(printInformation.dataFile)
                printInformation = JSON.parse(input);
            }
            this._renderer = new PhantomPdfRenderer(printInformation.pageSize,
                printInformation.orientation,
                printInformation.margins,
                printInformation.dpi,
                printInformation.outputPath);
            this._generate(printInformation.html, printInformation.coherenceId);
        }
    },

    onError: function (text, trace) {
        var error = { message: text, trace: trace };
        this._console.log(JSON.stringify(error)); //log the error in manual phantom console so that we can debug.
        this._output.errors.push(error);
    },

    onMessage: function (text) {
        this._output.messages.push(text);
    },

    _generate: function (html, coherenceId) {
        this._output = new PhantomOutput(coherenceId);

        var self = this;

        this._page.onCallback = function () {
            self._onPhantomCallback();
        };
        this._page.setContent(html, "http://localhost");
    },

    _createPage: function () {
        var page = this._pageFactory();
        page.viewportSize = { width: 1920, height: 1080 };
        return page;
    },

    _onPhantomCallback: function () {
        var renderResult = this._renderer.render(this._page);

        this._output.setResult(renderResult);
        this._outputAndWaitForNewInput();
    },

    _outputAndWaitForNewInput: function () {
        this._console.log(JSON.stringify(this._output));
        this.waitForInputThenGenerate();
    },

    _initializePageAndWait: function () {
        //unfortunately PhantomJs is getting older and older, need this weird warm up before it could load further input correctly.
        var self = this;
        this._page.onCallback = function () {
            self.waitForInputThenGenerate();
        };
        this._page.setContent("<html><script type='text/javascript'> window.onload = function () { window.callPhantom(); };</script></html>", "http://localhost");
    }
};
