var path = require('path');
var time_regex = /P((([0-9]*\.?[0-9]*)Y)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)W)?(([0-9]*\.?[0-9]*)D)?)?(T(([0-9]*\.?[0-9]*)H)?(([0-9]*\.?[0-9]*)M)?(([0-9]*\.?[0-9]*)S)?)?/;
try {
    var key = require(path.join(__dirname, '../config/api_key.js'));
} catch(e) {
    console.log("Error - missing file");
    console.log("Seems you forgot to create the file api_key.js in /server/config/. Have a look at api_key.example.js.");
    process.exit();
}

function get_correct_info(song_generated, channel, broadcast, callback) {
    channel = channel.replace(/ /g,'');
    request({
            type: "GET",
            url: "https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key="+key+"&id=" + song_generated.id,

    }, function(error, response, body) {
        try {
            var resp = JSON.parse(body);
            if(resp.items.length == 1) {
                var duration = parseInt(durationToSeconds(resp.items[0].contentDetails.duration));
                var title = resp.items[0].snippet.localized.title;
                if(title != song_generated.title || duration < parseInt(song_generated.duration)) {
                    if(title != song_generated.title) {
                        song_generated.title = title;
                    }
                    if(duration < parseInt(song_generated.duration)) {
                        song_generated.duration = duration;
                        song_generated.start = 0;
                        song_generated.end = duration;
                    }
                    db.collection(channel).update({"id": song_generated.id}, {
                        $set: {
                            "duration": song_generated.duration,
                            "start": song_generated.start,
                            "end": song_generated.end,
                            "title": song_generated.title,
                        }
                    }, function(err, docs) {
                        if(broadcast && docs.nModified == 1) {
                            song_generated.new_id = song_generated.id;
                            //if(song_generated.type == "video")
                            if(typeof(callback) == "function") {
                                callback(song_generated, true);
                            } else {
                                io.to(channel).emit("channel", {type: "changed_values", value: song_generated});
                            }
                        } else {
                            if(typeof(callback) == "function") {
                                callback(song_generated, true);
                            }
                        }
                    });
                } else {
                    if(typeof(callback) == "function") {
                        callback(song_generated, true);
                    }
                }
            } else {
                findSimilar(song_generated, channel, broadcast, callback)
            }
        } catch(e){
            if(typeof(callback) == "function") {
                callback({}, false);
            }
        }
    });
}

function check_error_video(msg, channel) {
    if(!msg.hasOwnProperty("id") || !msg.hasOwnProperty("title") ||
     typeof(msg.id) != "string" || typeof(msg.title) != "string") {
         var result = {
             id: {
                 expected: "string",
                 got: msg.hasOwnProperty("id") ? typeof(msg.id) : undefined,
             },
             title: {
                 expected: "string",
                 got: msg.hasOwnProperty("title") ? typeof(msg.title) : undefined,
             },
         };
        return;
    }
    if(msg.source == "soundcloud") return;
    channel = channel.replace(/ /g,'');
    request({
            type: "GET",
            url: "https://www.googleapis.com/youtube/v3/videos?part=id&key="+key+"&id=" + msg.id,

    }, function(error, response, body) {
        try {
            var resp = JSON.parse(body);
            if(resp.pageInfo.totalResults == 0) {
                findSimilar(msg, channel, true, undefined)
            }
        } catch(e){
            console.log(e);
        }
    });
}

function findSimilar(msg, channel, broadcast, callback) {
    channel = channel.replace(/ /g,'');
    var yt_url = "https://www.googleapis.com/youtube/v3/search?key="+key+"&videoEmbeddable=true&part=id&type=video&order=viewCount&safeSearch=none&maxResults=5&q=" + encodeURIComponent(msg.title);
    request({
        method: "GET",
        url: yt_url,
    }, function(error, response, body){
        var resp = JSON.parse(body);
        if(resp.items.length > 0) {
            var vid_url = "https://www.googleapis.com/youtube/v3/videos?part=contentDetails,snippet,id&key="+key+"&id=";
            for(var i = 0; i < resp.items.length; i++) {
                vid_url += resp.items[i].id.videoId + ",";
            }
            request({
                    type: "GET",
                    url: vid_url
            }, function(error, response, body) {
                var resp = JSON.parse(body);
                var found = false;
                var element = {};
                for(var i = 0; i < resp.items.length; i++) {
                    if(similarity(resp.items[i].snippet.localized.title, msg.title) > 0.75) {
                        found = true;
                        element = {
                            title: resp.items[i].snippet.localized.title,
                            duration: parseInt(durationToSeconds(resp.items[i].contentDetails.duration)),
                            id: resp.items[i].id,
                            start: 0,
                            end: parseInt(durationToSeconds(resp.items[i].contentDetails.duration)),
                        }
                        break;
                    }
                }
                if(found) {
                    db.collection(channel).update({"id": msg.id}, {
                        $set: element
                    }, function(err, docs) {
                        if(docs.nModified == 1 && broadcast) {
                            element.new_id = element.id;
                            element.id = msg.id;
                            if(!callback) {
                                io.to(channel).emit("channel", {type: "changed_values", value: element});
                            }
                        }
                        if(typeof(callback) == "function") {
                            msg.title = element.title;
                            msg.id = element.id;
                            msg.duration = element.duration;
                            msg.start = element.start;
                            msg.end = element.end;
                            callback(msg, true);
                        }
                    });
                } else if(typeof(callback) == "function") {
                    callback({}, false);
                }
            });
        }
    });
}

function similarity(s1, s2) {
  var longer = s1;
  var shorter = s2;
  if (s1.length < s2.length) {
    longer = s2;
    shorter = s1;
  }
  var longerLength = longer.length;
  if (longerLength == 0) {
    return 1.0;
  }
  return (longerLength - editDistance(longer, shorter)) / parseFloat(longerLength);
}

function editDistance(s1, s2) {
  s1 = s1.toLowerCase();
  s2 = s2.toLowerCase();

  var costs = new Array();
  for (var i = 0; i <= s1.length; i++) {
    var lastValue = i;
    for (var j = 0; j <= s2.length; j++) {
      if (i == 0)
        costs[j] = j;
      else {
        if (j > 0) {
          var newValue = costs[j - 1];
          if (s1.charAt(i - 1) != s2.charAt(j - 1))
            newValue = Math.min(Math.min(newValue, lastValue),
              costs[j]) + 1;
          costs[j - 1] = lastValue;
          lastValue = newValue;
        }
      }
    }
    if (i > 0)
      costs[s2.length] = lastValue;
  }
  return costs[s2.length];
}

function durationToSeconds(duration) {
    var matches = duration.match(time_regex);
    hours= parseInt(matches[12])||0;
    minutes= parseInt(matches[14])||0;
    seconds= parseInt(matches[16])||0;
    return hours*60*60+minutes*60+seconds;
}

module.exports.check_error_video = check_error_video;
module.exports.get_correct_info = get_correct_info;
