/*global phantom:true */

console.log("Starting Discourse Smoke Test");

var system = require("system");

if (system.args.length !== 2) {
  console.log("Expecting: phantomjs {smoke_test.js} {url}");
  phantom.exit(1);
}

var TIMEOUT = 15000;
var page = require("webpage").create();

page.viewportSize = {
  width: 1366,
  height: 768
};

// In the browser, when the cookies are disabled, it also disables the localStorage
// Here, we're mocking that behavior and making sure the application doesn't blow up
page.onInitialized = function() {
  page.evaluate(function() {
    localStorage["disableLocalStorage"] = true;
  });
};

page.onConsoleMessage = function(msg) {
  console.log(msg);
}

page.waitFor = function(desc, fn, cb) {
  var start = +new Date();

  var check = function() {
    var r;

    try { r = page.evaluate(fn); } catch (err) { }

    var diff = (+new Date()) - start;

    if (r) {
      console.log("PASSED: " + desc + " - " + diff + "ms");
      cb(true);
    } else {
      if (diff > TIMEOUT) {
        console.log("FAILED: " + desc + " - " + diff + "ms");
        page.render('/tmp/failed.png');
        cb(false);
      } else {
        setTimeout(check, 25);
      }
    }
  };

  check();
};


var actions = [];

function test(desc, fn) {
  actions.push({ test: fn, desc: desc });
};

function wait(delay) {
  actions.push({ wait: delay });
}

function exec(desc, fn) {
  actions.push({ exec: fn, desc: desc });
};

function execAsync(desc, delay, fn) {
  actions.push({ execAsync: fn, delay: delay, desc: desc });
};

function upload(input, path) {
  actions.push({ upload: path, input: input });
};

function screenshot(filename) {
  actions.push({ screenshot: filename });
}

function run() {
  var allPassed = true;

  var done = function() {
    console.log(allPassed ? "ALL PASSED" : "SMOKE TEST FAILED");
    phantom.exit();
  };

  var performNextAction = function() {
    if (!allPassed || actions.length === 0) {
      done();
    } else {
      var action = actions[0];
      actions = actions.splice(1);
      if (action.test) {
        page.waitFor(action.desc, action.test, function(success) {
          allPassed = allPassed && success;
          performNextAction();
        });
      } else if (action.exec) {
        console.log("EXEC: " + action.desc);
        page.evaluate(action.exec);
        performNextAction();
      } else if (action.execAsync) {
        console.log("EXEC ASYNC: " + action.desc + " - " + action.delay + "ms");
        setTimeout(function() {
          page.evaluate(action.execAsync);
          performNextAction();
        }, action.delay);
      } else if (action.upload) {
        console.log("UPLOAD: " + action.upload);
        page.uploadFile(action.input, action.upload);
        performNextAction();
      } else if (action.screenshot) {
        console.log("SCREENSHOT: " + action.screenshot);
        page.render(action.screenshot);
        performNextAction();
      } else if (action.wait) {
        console.log("WAIT: " + action.wait + "ms");
        setTimeout(function() {
          performNextAction();
        }, action.wait);
      }
    }
  };

  performNextAction();
};

var runTests = function() {

  test("expect a log in button", function() {
    return $(".login-button").text().trim() === "Log In";
  });

  test("at least one topic shows up", function() {
    return document.querySelector(".topic-list tbody tr");
  });

  execAsync("navigate to 1st topic", 500, function() {
    if ($(".main-link > a:first").length > 0) {
      $(".main-link > a:first").click(); // topic list page
    } else {
      $(".featured-topic a.title:first").click(); // categories page
    }
  });

  test("at least one post body", function() {
    return document.querySelector(".topic-post");
  });

  execAsync("click on the 1st user", 500, function() {
    // remove the popup action for testing
    $(".topic-meta-data a:first").data("ember-action", "");
    $(".topic-meta-data a:first").focus().click();
  });

  test("user has details", function() {
    return document.querySelector("#user-card .names");
  });

  exec("open login modal", function() {
    $(".login-button").click();
  });

  test("login modal is open", function() {
    return document.querySelector(".login-modal");
  });

  exec("type in credentials & log in", function() {
    $("#login-account-name").val("smoke_user").trigger("change");
    $("#login-account-password").val("P4ssw0rd").trigger("change");
    $(".login-modal .btn-primary").click();
  });

  test("is logged in", function() {
    return document.querySelector(".current-user");
  });

  exec("go home", function() {
    $('#site-logo').click();
  });

  test("it shows a topic list", function() {
    return document.querySelector(".topic-list");
  });

  exec("open composer", function() {
    $("#create-topic").click();
  });

  test('the editor is visible', function() {
    return document.querySelector(".d-editor");
  });

  exec("compose new topic", function() {
    var date = " (" + (+new Date()) + ")",
        title = "This is a new topic" + date,
        post = "I can write a new topic inside the smoke test!" + date + "\n\n";

    $("#reply-title").val(title).trigger("change");
    $("#reply-control .d-editor-input").val(post).trigger("change");
    $("#reply-control .d-editor-input").focus()[0].setSelectionRange(post.length, post.length);
  });

  test("updates preview", function() {
    return document.querySelector(".d-editor-preview p");
  });

  exec("open upload modal", function() {
    $(".d-editor-button-bar .upload").click();
  });

  test("upload modal is open", function() {
    return document.querySelector("#filename-input");
  });

  // TODO: Looks like PhantomJS 2.0.0 has a bug with `uploadFile`
  // which breaks this code.

  // upload("#filename-input", "spec/fixtures/images/large & unoptimized.png");
  // test("the file is inserted into the input", function() {
  //   return document.getElementById('filename-input').files.length
  // });
  // screenshot('/tmp/upload-modal.png');
  //
  // test("upload modal is open", function() {
  //   return document.querySelector("#filename-input");
  // });
  //
  // exec("click upload button", function() {
  //   $(".modal .btn-primary").click();
  // });
  //
  // test("image is uploaded", function() {
  //   return document.querySelector(".cooked img");
  // });

  exec("submit the topic", function() {
    $("#reply-control .create").click();
  });

  test("topic is created", function() {
    return document.querySelector(".fancy-title");
  });

  exec("click reply button", function() {
    $(".post-controls:first .create").click();
  });

  test("composer is open", function() {
    return document.querySelector("#reply-control .d-editor-input");
  });

  exec("compose reply", function() {
    var post = "I can even write a reply inside the smoke test ;) (" + (+new Date()) + ")";
    $("#reply-control .d-editor-input").val(post).trigger("change");
  });

  test("waiting for the preview", function() {
    return $(".d-editor-preview").text().trim().indexOf("I can even write") === 0;
  });

  execAsync("submit the reply", 6000, function() {
    $("#reply-control .create").click();
  });

  test("reply is created", function() {
    return !document.querySelector(".saving-text")
        && $(".topic-post").length === 2;
  });

  run();
};

phantom.clearCookies();
page.open(system.args[1], function() {
  page.evaluate(function() { localStorage.clear(); });
  console.log("OPENED: " + system.args[1]);
  runTests();
});