import { type ReposConfiguration } from "../../src/configTypes.ts"

/**
 * Returns links to various pages used by the default template. Will return a link
 * that assumes you want to stay on the current ref, unless you give a new ref in
 * the function argument. E.g if you are currently at /tags/v-1-0/, and you call
 * the commits() function, it'll give you /tag/v-1-0/commits, unless you pass in
 * an argument like commits({refName: 'main', refType: 'branch'}), in which case
 * it'll give you /branch/main/commits.
 */
type CurrentRefArgs = {
  reposConfig: ReposConfiguration,
  slugify: Function,
  currentRepoName: string,
  currentRefName: string,
  currentRefType: 'branch' | 'tag' | 'commit'
}
export const NavHelper = (args: CurrentRefArgs) => {
  const reposPath = args.reposConfig.path || ""

  // These two aren't actually used by any pages, but they're in almost
  // every page URL. E.g. all of them start with 'repos/my-repo-name'
  // or 'repos/my-repo-name/branches.'
  const repoBasePath = `${reposPath}/${args.slugify(args.currentRepoName)}`

  const refPath = (refName, refType) => {
    if (refType === 'commit'
        || (refType === 'branch' && refName === args.reposConfig.repos[args.currentRepoName].defaultBranch)) {
      return repoBasePath
    }
    return `${repoBasePath}/${refType}/${args.slugify(refName)}`
  }

  type RefArgument = {
    refName: string,
    refType: 'branch' | 'tag'
  }

  return {
    rootPath: () => {
      if (reposPath === "") {
        return "/"
      }
      else {
        return reposPath + '/'
      }
    },
    repoHomePath: () => {
      return repoBasePath
    },
    refHome: (newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return refPath(refName, refType)
    },
    file: (filePath: string, newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/files/${filePath.split('/')
        .map((pathPart) => {
          return pathPart.split('.').map((subPart) => {
            return args.slugify(subPart)
          }).join('.')
        }).join('/')}.html`
    },
    raw: (filePath: string, newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/raw/${filePath.split('/')
        .map((filePart) => {
          return filePart.split('.').map((subPart) => {
            return args.slugify(subPart)
          }).join('.')
        }).join('/')}`
    },
    files: (newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/files`
    },
    commit: (hash: string) => {
      return `${repoBasePath}/commits/${hash}`
    },
    commits: (pageNum: number, newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/commits/page${pageNum.toString()}`
    },
    branches: (newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/branches`
    },
    tags: (newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/tags`
    },
    rssFeed: (newRef: RefArgument = null) => {
      const refName = newRef?.refName || args.currentRefName
      const refType = newRef?.refType || args.currentRefType

      return `${refPath(refName, refType)}/commits.xml`
    },
    homepageButtons: args.reposConfig.repos[args.currentRepoName].defaultTemplateConfiguration?.homepageButtons || []
  }
}

