// dependencies
var request = require("request");
// require('request-debug')(request);


// wrappers and default configurations
request.defaults({
    headers: {
        'User-Agent': 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5'
    }
});


// Some app variables
var _is_secure                      = false;
var _url_endpoint_protocol          = (_is_secure != false) ? "https" : "http";
var _url_endpoint_prefix_host       = _url_endpoint_protocol + "://" + "instagram.com";
var _url_endpoint_prefix_username   = _url_endpoint_prefix_host;
var _url_endpoint_prefix_tag        = _url_endpoint_prefix_host + "/explore/tags";
var _url_endpoint_pic_info          = _url_endpoint_protocol + "://" + "api.instagram.com/oembed/?hidecaption=0&url=https://instagram.com/p/";



// Instagram Scraper Base Class

function InstagramClient() {
    // Initializing process queue and processed data structures
    this.procQueue      =   [];
    this.callbacks      =   {
                                dumpData        : null,
                                next            : null,
                                queueComplete   : null
                            }
}


// init
InstagramClient.prototype.init = function() {
    if (this.procQueue.length) {
        this.parsePage();
    } else {
        console.log("Queue Complete");
        
        // callback to dump data
        if(this.callbacks.queueComplete) {
            this.callbacks.queueComplete.call(this);
        }
    }
};


// for now next is same as init
InstagramClient.prototype.next = InstagramClient.prototype.init;


// Data dumper
InstagramClient.prototype.dumpData = function (data) {

    // callback to dump data
    if(this.callbacks.dumpData) {
        this.callbacks.dumpData.call(this, data);
    }

    // callback for next
    if(this.callbacks.next) {
        var callback = this.callbacks.next;
    }

    this.next(callback);
}


// HTTP Client to load the page
InstagramClient.prototype.parsePage = function() {
    var myClient    = this;
    var procQueue   = myClient.procQueue;
    var url         = myClient.prepareURL();

    request(url, function(err, res, body) {

        if (!err && res.statusCode == 200) {

            myClient.parseAction.call(myClient, res, body)            

        } else {

            console.error("Error with: "    + url);
            console.log("Err: "             + err);
            console.log("Status: "          + res.statusCode);

            // callback for next
            if(myClient.callbacks.next) {
                var callback = myClient.callbacks.next;
            }

            myClient.next(callback);

        }

    });    

};


// prepare URL for the parser
InstagramClient.prototype.prepareURL = function(res, body, metaData) {}


// page parser, each client has its own parsing logic 
InstagramClient.prototype.parseAction = function(res, body, metaData) {}


// Add items to Queue
InstagramClient.prototype.addQueue = function(queueItems) {
    if (!queueItems || !queueItems.length)
        return false;

    for (var i = 0; i < queueItems.length; i++) {
        this.procQueue.push(queueItems[i]);
    }

    return this.procQueue.slice();
}




// inherited scraper clients


// tags parser
var tagsParserClient = function(){ InstagramClient.call(this) };
tagsParserClient.prototype = Object.create(InstagramClient.prototype);

tagsParserClient.prototype.prepareURL = function function_name () {
    return _url_endpoint_prefix_tag + '/' + this.procQueue.pop();
}

tagsParserClient.prototype.parseAction  = function(res, body) {
    
    var data            = [];
    var matches         = body.match(/\"nodes\":(\[{\"code\".*?\])/)

    if(matches[1]) {
        var pics = JSON.parse(matches[1].replace('\\n', ''));

        for (index in pics) {
            var thisPic = pics[index];
            if (!thisPic.is_video) {
                data.push(thisPic.code);
            }
        }

        this.dumpData(data);
    }

}


// pics parser
var picsParserClient = function(){ InstagramClient.call(this) };
picsParserClient.prototype = Object.create(InstagramClient.prototype);

picsParserClient.prototype.prepareURL = function function_name () {
    return _url_endpoint_pic_info + this.procQueue.pop() + '/';
}

picsParserClient.prototype.parseAction  = function(res, body) {

    var data = JSON.parse(body);
        data = {
                username    : data.author_name,
                user_url    : data.author_url,
                user_id     : data.author_id
               }

    this.dumpData(data);

};


// profile parser
var profileParserClient = function(){ InstagramClient.call(this) };
profileParserClient.prototype = Object.create(InstagramClient.prototype);

profileParserClient.prototype.prepareURL = function function_name () {
    return _url_endpoint_prefix_username + '/' + this.procQueue.pop();
}

profileParserClient.prototype.parseAction = function(res, body) {

    var matches     = body.match(/window._sharedData = ((.*));<\/script>/i);
    var data        = JSON.parse(matches[1].replace('\\n', ''));
        
        data        = data.entry_data.ProfilePage[0].user;
        data        = {
                        username    : data.username,
                        full_name   : data.full_name,
                        counts      : data.counts,
                        id          : data.id,
                        isVerified  : data.isVerified
                      }

    this.dumpData(data);

};


//export
module.exports = {
  tagsParser    : tagsParserClient,
  picsParser    : picsParserClient,
  profileParser : profileParserClient
};
