import { parse } from "../../../base/common/glob.mjs";
import { Mimes } from "../../../base/common/mime.mjs";
import { Schemas } from "../../../base/common/network.mjs";
import { posix, basename } from "../../../base/common/path.mjs";
import { DataUri } from "../../../base/common/resources.mjs";
import { startsWithUTF8BOM } from "../../../base/common/strings.mjs";
let registeredAssociations = [];
let nonUserRegisteredAssociations = [];
let userRegisteredAssociations = [];
function registerPlatformLanguageAssociation(association, warnOnOverwrite = false) {
  _registerLanguageAssociation(association, false, warnOnOverwrite);
}
function _registerLanguageAssociation(association, userConfigured, warnOnOverwrite) {
  const associationItem = toLanguageAssociationItem(association, userConfigured);
  registeredAssociations.push(associationItem);
  if (!associationItem.userConfigured) {
    nonUserRegisteredAssociations.push(associationItem);
  } else {
    userRegisteredAssociations.push(associationItem);
  }
  if (warnOnOverwrite && !associationItem.userConfigured) {
    registeredAssociations.forEach((a) => {
      if (a.mime === associationItem.mime || a.userConfigured) {
        return;
      }
      if (associationItem.extension && a.extension === associationItem.extension) {
        console.warn(`Overwriting extension <<${associationItem.extension}>> to now point to mime <<${associationItem.mime}>>`);
      }
      if (associationItem.filename && a.filename === associationItem.filename) {
        console.warn(`Overwriting filename <<${associationItem.filename}>> to now point to mime <<${associationItem.mime}>>`);
      }
      if (associationItem.filepattern && a.filepattern === associationItem.filepattern) {
        console.warn(`Overwriting filepattern <<${associationItem.filepattern}>> to now point to mime <<${associationItem.mime}>>`);
      }
      if (associationItem.firstline && a.firstline === associationItem.firstline) {
        console.warn(`Overwriting firstline <<${associationItem.firstline}>> to now point to mime <<${associationItem.mime}>>`);
      }
    });
  }
}
function toLanguageAssociationItem(association, userConfigured) {
  return {
    id: association.id,
    mime: association.mime,
    filename: association.filename,
    extension: association.extension,
    filepattern: association.filepattern,
    firstline: association.firstline,
    userConfigured,
    filenameLowercase: association.filename ? association.filename.toLowerCase() : void 0,
    extensionLowercase: association.extension ? association.extension.toLowerCase() : void 0,
    filepatternLowercase: association.filepattern ? parse(association.filepattern.toLowerCase()) : void 0,
    filepatternOnPath: association.filepattern ? association.filepattern.indexOf(posix.sep) >= 0 : false
  };
}
function clearPlatformLanguageAssociations() {
  registeredAssociations = registeredAssociations.filter((a) => a.userConfigured);
  nonUserRegisteredAssociations = [];
}
function getMimeTypes(resource, firstLine) {
  let path;
  if (resource) {
    switch (resource.scheme) {
      case Schemas.file:
        path = resource.fsPath;
        break;
      case Schemas.data: {
        const metadata = DataUri.parseMetaData(resource);
        path = metadata.get(DataUri.META_DATA_LABEL);
        break;
      }
      default:
        path = resource.path;
    }
  }
  if (!path) {
    return [Mimes.unknown];
  }
  path = path.toLowerCase();
  const filename = basename(path);
  const configuredLanguage = getMimeByPath(path, filename, userRegisteredAssociations);
  if (configuredLanguage) {
    return [configuredLanguage, Mimes.text];
  }
  const registeredLanguage = getMimeByPath(path, filename, nonUserRegisteredAssociations);
  if (registeredLanguage) {
    return [registeredLanguage, Mimes.text];
  }
  if (firstLine) {
    const firstlineLanguage = getMimeByFirstline(firstLine);
    if (firstlineLanguage) {
      return [firstlineLanguage, Mimes.text];
    }
  }
  return [Mimes.unknown];
}
function getMimeByPath(path, filename, associations) {
  var _a;
  let filenameMatch = void 0;
  let patternMatch = void 0;
  let extensionMatch = void 0;
  for (let i = associations.length - 1; i >= 0; i--) {
    const association = associations[i];
    if (filename === association.filenameLowercase) {
      filenameMatch = association;
      break;
    }
    if (association.filepattern) {
      if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) {
        const target = association.filepatternOnPath ? path : filename;
        if ((_a = association.filepatternLowercase) === null || _a === void 0 ? void 0 : _a.call(association, target)) {
          patternMatch = association;
        }
      }
    }
    if (association.extension) {
      if (!extensionMatch || association.extension.length > extensionMatch.extension.length) {
        if (filename.endsWith(association.extensionLowercase)) {
          extensionMatch = association;
        }
      }
    }
  }
  if (filenameMatch) {
    return filenameMatch.mime;
  }
  if (patternMatch) {
    return patternMatch.mime;
  }
  if (extensionMatch) {
    return extensionMatch.mime;
  }
  return void 0;
}
function getMimeByFirstline(firstLine) {
  if (startsWithUTF8BOM(firstLine)) {
    firstLine = firstLine.substr(1);
  }
  if (firstLine.length > 0) {
    for (let i = registeredAssociations.length - 1; i >= 0; i--) {
      const association = registeredAssociations[i];
      if (!association.firstline) {
        continue;
      }
      const matches = firstLine.match(association.firstline);
      if (matches && matches.length > 0) {
        return association.mime;
      }
    }
  }
  return void 0;
}
export {
  clearPlatformLanguageAssociations,
  getMimeTypes,
  registerPlatformLanguageAssociation
};
