var mapSize = {{globalMapSize}};
var containingCompName = "{{containingCompName}}";
var mapcompLayerName = "{{mapcompLayerName}}";
var linkMapcompName = {{linkMapcompName}};

var interpolationStyleTransitionArea = [{{interpolationStyleTransitionArea}}];

if(linkMapcompName){
    var linkMapcompPivot = null;
    var linkMapcompOffset = null;
    try{
        linkMapcompPivot = comp(linkMapcompName).layer("{{mapPivotLayerName}}")
        linkMapcompOffset = effect("{{mapPivotLinkMapcompOffsetName}}").param(1)
    }catch(e){}
}
if(linkMapcompPivot){
    if(linkMapcompOffset && (linkMapcompOffset[0] != 0 || linkMapcompOffset[1] != 0)){
        [linkMapcompPivot.transform.anchorPoint.value[0] + linkMapcompOffset[0], linkMapcompPivot.transform.anchorPoint.value[1] + linkMapcompOffset[1], 0]
    }else{
        [linkMapcompPivot.transform.anchorPoint.value[0], linkMapcompPivot.transform.anchorPoint.value[1], 0]
    }
}else{
    var Clip = function(n, minValue, maxValue) {
        return Math.min(Math.max(n, minValue), maxValue);
    }
    var LatToPixelY = function(latitude){
        var min_lat= -85.05112878;
        var max_lat= 85.05112878;
        latitude = Clip(latitude, min_lat, max_lat);
        var sinLatitude = Math.sin(latitude * Math.PI / 180);
        var y = 0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI);
        var pixelY = y * mapSize /*+ 0.5*/;
        pixelY = Clip(pixelY, 0, mapSize - 1);
        return pixelY
    }
    var LonToPixelX = function(longitude){
        var x = (longitude + 180) / 360;
        var pixelX = x * mapSize /*+ 0.5*/;
        return pixelX
    }
    var LatLongToPixelXY = function(latitude, longitude) {
        return [LonToPixelX(longitude), LatToPixelY(latitude)];
    }
    var getInterpolationKeyframes = function(valObj, myTime){
        var n = 0;
        var key1 = null;
        var key2 = null;
        if (valObj.numKeys > 1) {
            n = valObj.nearestKey(myTime).index;
            if (valObj.key(n).time > myTime) {
                n--
            }
            if(n > 0 && n+1 <= valObj.numKeys){
                var key1 = valObj.key(n);
                var key2 = valObj.key(n + 1);
            }
        }
        return {
            key1:key1,
            key2:key2
        }
    }
    var transformLinear = function(ix, ix1, ix2, iy1, iy2) {
        var m = (iy2 - iy1) / (ix2 - ix1);
        var n = (m * -1) * ix1 + iy1;
        var y = m * ix + n;
        return y;
    }
    var getZoomRelatedPositionX = function(longitude, time){
        if(time != undefined){
            var pScale = transform.scale.valueAtTime(time)[1];
        }else{
            var pScale = pivotScale;
        }
        var PixelX = LonToPixelX(longitude);
        var PixelXDiff = mapSize/2-PixelX;
        return PixelXDiff * pScale/100 + thisComp.width/2;
    }
    var getZoomRelatedPositionY = function(lat, time){
        if(time != undefined){
            var pScale = transform.scale.valueAtTime(time)[1];
        }else{
            var pScale = pivotScale;
        }
        var PixelY = LatToPixelY(lat);
        var PixelYDiff = mapSize/2-PixelY;
        return PixelYDiff * pScale/100 + thisComp.height/2;
    }
    var getZoomRelatedPosition = function(lat, longitude, time){
        return [getZoomRelatedPositionX(longitude, time), getZoomRelatedPositionY(lat, time)];
    }
    var transformPositionToAnchorPoint = function(posOffset, anchorOffset, pos){
        var val = (posOffset + pos * -1)*100;
        return [val[0]/transform.scale[0]/thisComp.pixelAspect, val[1]/transform.scale[1]]+anchorOffset
    }

    var controlLayer = comp(containingCompName).layer(mapcompLayerName);
    var LatitudeEff = controlLayer.effect("Latitude").param(1);
    var LongitudeEff = controlLayer.effect("Longitude").param(1);
    var ZoomEff = controlLayer.effect("Zoom").param(1);
    var diffTime = controlLayer.startTime;
    var myTime = time + diffTime;
    var LongKeys = getInterpolationKeyframes(LongitudeEff, myTime);
    var LatKeys = getInterpolationKeyframes(LatitudeEff, myTime);
    var ZoomKeys = getInterpolationKeyframes(ZoomEff, myTime);
    var pivotScale = transform.scale[1];
    var pixelXY = getZoomRelatedPosition(LatitudeEff.valueAtTime(myTime), LongitudeEff.valueAtTime(myTime));
    var zoomExpDiff = 0;
    var positionExpDiff = 0;
    var positionNoExp = 0;
    var absZoomKeyValDiff = null;
    if(ZoomKeys.key1 && ZoomKeys.key2){
        absZoomKeyValDiff = Math.abs(ZoomKeys.key1.value-ZoomKeys.key2.value);
    }

    if(absZoomKeyValDiff && absZoomKeyValDiff > interpolationStyleTransitionArea[0]){
        var pivotScaleNoExp = transformLinear(myTime, ZoomKeys.key1.time, ZoomKeys.key2.time, transform.scale.valueAtTime(ZoomKeys.key1.time-diffTime)[1], transform.scale.valueAtTime(ZoomKeys.key2.time-diffTime)[1]);
        zoomExpDiff = pivotScaleNoExp-pivotScale;
        if(LongKeys.key1 && LongKeys.key2 && (LongKeys.key1.value != LongKeys.key2.value)){
            var expRelatedTime1 = Math.max(ZoomKeys.key1.time, LongKeys.key1.time);
            var expRelatedTime2 = Math.min(ZoomKeys.key2.time, LongKeys.key2.time);
            var pixelXZoomKey1 = getZoomRelatedPositionX(LongitudeEff.valueAtTime(expRelatedTime1),expRelatedTime1-diffTime);
            var pixelXZoomKey2 = getZoomRelatedPositionX(LongitudeEff.valueAtTime(expRelatedTime2),expRelatedTime2-diffTime);
            var positionNoExp = transformLinear(myTime, expRelatedTime1,expRelatedTime2, pixelXZoomKey1, pixelXZoomKey2);
            if(zoomExpDiff){
                var pivotScaleNoExpAtExpRelatedTime1 = transformLinear(expRelatedTime1, ZoomKeys.key1.time, ZoomKeys.key2.time, transform.scale.valueAtTime(ZoomKeys.key1.time-diffTime)[1], transform.scale.valueAtTime(ZoomKeys.key2.time-diffTime)[1])-transform.scale.valueAtTime(expRelatedTime1-diffTime)[1];
                var pivotScaleNoExpAtExpRelatedTime2 = transformLinear(expRelatedTime2, ZoomKeys.key1.time, ZoomKeys.key2.time, transform.scale.valueAtTime(ZoomKeys.key1.time-diffTime)[1], transform.scale.valueAtTime(ZoomKeys.key2.time-diffTime)[1])-transform.scale.valueAtTime(expRelatedTime2-diffTime)[1];
                var deltaFlatPositionExpDiff = transformLinear(myTime, expRelatedTime1, expRelatedTime2, pivotScaleNoExpAtExpRelatedTime1, pivotScaleNoExpAtExpRelatedTime2)
                positionExpDiff = transformLinear(zoomExpDiff-deltaFlatPositionExpDiff, 0, transform.scale.valueAtTime(expRelatedTime2-diffTime)[1]-transform.scale.valueAtTime(expRelatedTime1-diffTime)[1], 0, pixelXZoomKey2 - pixelXZoomKey1);
                if(absZoomKeyValDiff < interpolationStyleTransitionArea[1]){
                    pixelXY[0] = transformLinear(absZoomKeyValDiff, interpolationStyleTransitionArea[0], interpolationStyleTransitionArea[1], pixelXY[0], positionNoExp - positionExpDiff);
                }else{
                    pixelXY[0] = positionNoExp - positionExpDiff;
                }
            }
        }
        if(LatKeys.key1 && LatKeys.key2 && (LatKeys.key1.value != LatKeys.key2.value)){
            var expRelatedTime1 = Math.max(ZoomKeys.key1.time, LatKeys.key1.time);
            var expRelatedTime2 = Math.min(ZoomKeys.key2.time, LatKeys.key2.time);
            var pixelXZoomKey1 = getZoomRelatedPositionY(LatitudeEff.valueAtTime(expRelatedTime1),expRelatedTime1-diffTime);
            var pixelXZoomKey2 = getZoomRelatedPositionY(LatitudeEff.valueAtTime(expRelatedTime2),expRelatedTime2-diffTime);
            var positionNoExp = transformLinear(myTime, expRelatedTime1,expRelatedTime2, pixelXZoomKey1, pixelXZoomKey2);
            if(zoomExpDiff){
                var pivotScaleNoExpAtExpRelatedTime1 = transformLinear(expRelatedTime1, ZoomKeys.key1.time, ZoomKeys.key2.time, transform.scale.valueAtTime(ZoomKeys.key1.time-diffTime)[1], transform.scale.valueAtTime(ZoomKeys.key2.time-diffTime)[1])-transform.scale.valueAtTime(expRelatedTime1-diffTime)[1];
                var pivotScaleNoExpAtExpRelatedTime2 = transformLinear(expRelatedTime2, ZoomKeys.key1.time, ZoomKeys.key2.time, transform.scale.valueAtTime(ZoomKeys.key1.time-diffTime)[1], transform.scale.valueAtTime(ZoomKeys.key2.time-diffTime)[1])-transform.scale.valueAtTime(expRelatedTime2-diffTime)[1];
                var deltaFlatPositionExpDiff = transformLinear(myTime, expRelatedTime1, expRelatedTime2, pivotScaleNoExpAtExpRelatedTime1, pivotScaleNoExpAtExpRelatedTime2)
                positionExpDiff = transformLinear(zoomExpDiff-deltaFlatPositionExpDiff, 0, transform.scale.valueAtTime(expRelatedTime2-diffTime)[1]-transform.scale.valueAtTime(expRelatedTime1-diffTime)[1], 0, pixelXZoomKey2 - pixelXZoomKey1);
                if(absZoomKeyValDiff < interpolationStyleTransitionArea[1]){
                    pixelXY[1] = transformLinear(absZoomKeyValDiff, interpolationStyleTransitionArea[0], interpolationStyleTransitionArea[1], pixelXY[1], positionNoExp - positionExpDiff);
                }else{
                    pixelXY[1] = positionNoExp - positionExpDiff;
                }
            }
        }
    }

    transformPositionToAnchorPoint([thisComp.width/2, thisComp.height/2], [mapSize/2, mapSize/2], [pixelXY[0], pixelXY[1]]);
}
