/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
import log from "../../../../log";
import arrayFind from "../../../../utils/array_find";
import objectAssign from "../../../../utils/object_assign";
import { convertSupplementalCodecsToRFC6381 } from "./convert_supplemental_codecs";
import { getWEBMHDRInformation } from "./get_hdr_information";
import parseRepresentationIndex from "./parse_representation_index";
import resolveBaseURLs from "./resolve_base_urls";
/**
 * Combine inband event streams from representation and
 * adaptation data.
 * @param {Object} representation
 * @param {Object} adaptation
 * @returns {undefined | Array.<Object>}
 */
function combineInbandEventStreams(representation, adaptation) {
    var newSchemeId = [];
    if (representation.children.inbandEventStreams !== undefined) {
        newSchemeId.push.apply(newSchemeId, representation.children.inbandEventStreams);
    }
    if (adaptation.children.inbandEventStreams !== undefined) {
        newSchemeId.push.apply(newSchemeId, adaptation.children.inbandEventStreams);
    }
    if (newSchemeId.length === 0) {
        return undefined;
    }
    return newSchemeId;
}
/**
 * Extract HDR information from manifest and codecs.
 * @param {Object}
 * @returns {Object | undefined}
 */
function getHDRInformation(_a) {
    var adaptationProfiles = _a.adaptationProfiles, essentialProperties = _a.essentialProperties, supplementalProperties = _a.supplementalProperties, manifestProfiles = _a.manifestProfiles, codecs = _a.codecs;
    var profiles = (adaptationProfiles !== null && adaptationProfiles !== void 0 ? adaptationProfiles : "") + (manifestProfiles !== null && manifestProfiles !== void 0 ? manifestProfiles : "");
    if (profiles.indexOf("http://dashif.org/guidelines/dash-if-uhd#hevc-hdr-pq10") !== -1) {
        if (codecs === "hvc1.2.4.L153.B0" ||
            codecs === "hev1.2.4.L153.B0") {
            return { colorDepth: 10,
                eotf: "pq",
                colorSpace: "rec2020" };
        }
    }
    var transferCharacteristicScheme = arrayFind(__spreadArray(__spreadArray([], (essentialProperties !== null && essentialProperties !== void 0 ? essentialProperties : []), true), (supplementalProperties !== null && supplementalProperties !== void 0 ? supplementalProperties : []), true), function (p) { return p.schemeIdUri === "urn:mpeg:mpegB:cicp:TransferCharacteristics"; });
    if (transferCharacteristicScheme !== undefined) {
        switch (transferCharacteristicScheme.value) {
            case "15":
                return undefined; // SDR
            case "16":
                return { eotf: "pq" };
            case "18":
                return { eotf: "hlg" };
        }
    }
    if (codecs !== undefined && /^vp(08|09|10)/.exec(codecs)) {
        return getWEBMHDRInformation(codecs);
    }
}
/**
 * Process intermediate representations to create final parsed representations.
 * @param {Array.<Object>} representationsIR
 * @param {Object} context
 * @returns {Array.<Object>}
 */
export default function parseRepresentations(representationsIR, adaptation, context) {
    var _a, _b, _c, _d, _e;
    var parsedRepresentations = [];
    var _loop_1 = function (representation) {
        // Compute Representation ID
        var representationID = representation.attributes.id !== undefined ?
            representation.attributes.id :
            (String(representation.attributes.bitrate) +
                (representation.attributes.height !== undefined ?
                    ("-".concat(representation.attributes.height)) :
                    "") +
                (representation.attributes.width !== undefined ?
                    ("-".concat(representation.attributes.width)) :
                    "") +
                (representation.attributes.mimeType !== undefined ?
                    ("-".concat(representation.attributes.mimeType)) :
                    "") +
                (representation.attributes.codecs !== undefined ?
                    ("-".concat(representation.attributes.codecs)) :
                    ""));
        // Avoid duplicate IDs
        while (parsedRepresentations.some(function (r) { return r.id === representationID; })) {
            representationID += "-dup";
        }
        // Retrieve previous version of the Representation, if one.
        var unsafelyBaseOnPreviousRepresentation = (_b = (_a = context
            .unsafelyBaseOnPreviousAdaptation) === null || _a === void 0 ? void 0 : _a.getRepresentation(representationID)) !== null && _b !== void 0 ? _b : null;
        var inbandEventStreams = combineInbandEventStreams(representation, adaptation);
        var availabilityTimeComplete = (_c = representation.attributes.availabilityTimeComplete) !== null && _c !== void 0 ? _c : context.availabilityTimeComplete;
        var availabilityTimeOffset = void 0;
        if (representation.attributes.availabilityTimeOffset !== undefined ||
            context.availabilityTimeOffset !== undefined) {
            availabilityTimeOffset = ((_d = representation.attributes.availabilityTimeOffset) !== null && _d !== void 0 ? _d : 0) +
                ((_e = context.availabilityTimeOffset) !== null && _e !== void 0 ? _e : 0);
        }
        var reprIndexCtxt = objectAssign({}, context, { availabilityTimeOffset: availabilityTimeOffset, availabilityTimeComplete: availabilityTimeComplete, unsafelyBaseOnPreviousRepresentation: unsafelyBaseOnPreviousRepresentation, adaptation: adaptation, inbandEventStreams: inbandEventStreams });
        var representationIndex = parseRepresentationIndex(representation, reprIndexCtxt);
        // Find bitrate
        var representationBitrate = void 0;
        if (representation.attributes.bitrate === undefined) {
            log.warn("DASH: No usable bitrate found in the Representation.");
            representationBitrate = 0;
        }
        else {
            representationBitrate = representation.attributes.bitrate;
        }
        var representationBaseURLs = resolveBaseURLs(context.baseURLs, representation.children.baseURLs);
        var cdnMetadata = representationBaseURLs.length === 0 ?
            // No BaseURL seems to be associated to this Representation, nor to the MPD,
            // but underlying segments might have one. To indicate that segments should
            // still be available through a CDN without giving any root CDN URL here,
            // we just communicate about an empty `baseUrl`, as documented.
            [{ baseUrl: "", id: undefined }] :
            representationBaseURLs.map(function (x) { return ({ baseUrl: x.url, id: x.serviceLocation }); });
        // Construct Representation Base
        var parsedRepresentation = { bitrate: representationBitrate, cdnMetadata: cdnMetadata, index: representationIndex,
            id: representationID };
        if (representation.children.supplementalProperties !== undefined &&
            arrayFind(representation.children.supplementalProperties, function (r) {
                return r.schemeIdUri === "tag:dolby.com,2018:dash:EC3_ExtensionType:2018" &&
                    r.value === "JOC";
            })) {
            parsedRepresentation.isSpatialAudio = true;
        }
        // Add optional attributes
        var codecs = void 0;
        if (representation.attributes.codecs !== undefined) {
            codecs = representation.attributes.codecs;
        }
        else if (adaptation.attributes.codecs !== undefined) {
            codecs = adaptation.attributes.codecs;
        }
        if (codecs !== undefined) {
            codecs = codecs === "mp4a.40.02" ? "mp4a.40.2" : codecs;
            parsedRepresentation.codecs = codecs;
        }
        var supplementalCodecs = void 0;
        if (representation.attributes.supplementalCodecs !== undefined) {
            supplementalCodecs = representation.attributes.supplementalCodecs;
        }
        else if (adaptation.attributes.supplementalCodecs !== undefined) {
            supplementalCodecs = adaptation.attributes.supplementalCodecs;
        }
        if (supplementalCodecs !== undefined) {
            parsedRepresentation.supplementalCodecs =
                convertSupplementalCodecsToRFC6381(supplementalCodecs);
        }
        if (representation.attributes.frameRate !== undefined) {
            parsedRepresentation.frameRate =
                representation.attributes.frameRate;
        }
        else if (adaptation.attributes.frameRate !== undefined) {
            parsedRepresentation.frameRate =
                adaptation.attributes.frameRate;
        }
        if (representation.attributes.height !== undefined) {
            parsedRepresentation.height =
                representation.attributes.height;
        }
        else if (adaptation.attributes.height !== undefined) {
            parsedRepresentation.height =
                adaptation.attributes.height;
        }
        if (representation.attributes.mimeType !== undefined) {
            parsedRepresentation.mimeType =
                representation.attributes.mimeType;
        }
        else if (adaptation.attributes.mimeType !== undefined) {
            parsedRepresentation.mimeType =
                adaptation.attributes.mimeType;
        }
        if (representation.attributes.width !== undefined) {
            parsedRepresentation.width =
                representation.attributes.width;
        }
        else if (adaptation.attributes.width !== undefined) {
            parsedRepresentation.width =
                adaptation.attributes.width;
        }
        var contentProtectionsIr = adaptation.children.contentProtections !== undefined ?
            adaptation.children.contentProtections :
            [];
        if (representation.children.contentProtections !== undefined) {
            contentProtectionsIr.push.apply(contentProtectionsIr, representation.children.contentProtections);
        }
        if (contentProtectionsIr.length > 0) {
            var contentProtections = contentProtectionsIr
                .reduce(function (acc, cp) {
                var _a;
                var systemId;
                if (cp.attributes.schemeIdUri !== undefined &&
                    cp.attributes.schemeIdUri.substring(0, 9) === "urn:uuid:") {
                    systemId = cp.attributes.schemeIdUri.substring(9)
                        .replace(/-/g, "")
                        .toLowerCase();
                }
                if (cp.attributes.keyId !== undefined && cp.attributes.keyId.length > 0) {
                    var kidObj = { keyId: cp.attributes.keyId, systemId: systemId };
                    if (acc.keyIds === undefined) {
                        acc.keyIds = [kidObj];
                    }
                    else {
                        acc.keyIds.push(kidObj);
                    }
                }
                if (systemId !== undefined) {
                    var cencPssh = cp.children.cencPssh;
                    var values = [];
                    for (var _i = 0, cencPssh_1 = cencPssh; _i < cencPssh_1.length; _i++) {
                        var data = cencPssh_1[_i];
                        values.push({ systemId: systemId, data: data });
                    }
                    if (values.length > 0) {
                        var cencInitData = arrayFind(acc.initData, function (i) { return i.type === "cenc"; });
                        if (cencInitData === undefined) {
                            acc.initData.push({ type: "cenc", values: values });
                        }
                        else {
                            (_a = cencInitData.values).push.apply(_a, values);
                        }
                    }
                }
                return acc;
            }, { keyIds: undefined, initData: [] });
            if (Object.keys(contentProtections.initData).length > 0 ||
                (contentProtections.keyIds !== undefined &&
                    contentProtections.keyIds.length > 0)) {
                parsedRepresentation.contentProtections = contentProtections;
            }
        }
        parsedRepresentation.hdrInfo =
            getHDRInformation({ adaptationProfiles: adaptation.attributes.profiles,
                supplementalProperties: adaptation.children
                    .supplementalProperties,
                essentialProperties: adaptation.children.essentialProperties,
                manifestProfiles: context.manifestProfiles, codecs: codecs });
        parsedRepresentations.push(parsedRepresentation);
    };
    for (var _i = 0, representationsIR_1 = representationsIR; _i < representationsIR_1.length; _i++) {
        var representation = representationsIR_1[_i];
        _loop_1(representation);
    }
    return parsedRepresentations;
}
