import m from 'mithril'
import { type Repository } from '../src/dataTypes.ts'
import { NavHelper } from './helpers/nav.ts'
import htmlPage from './common/htmlPage.ts'

export default async (reposConfig: any, eleventyConfig: any, data: any) => {
  const repo: Repository = data.currentRepo
  const ref: Repository['branches'][0] | Repository['tags'][0] = data.currentRef
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
  const slugify = eleventyConfig.getFilter("slugify")
  const getReadMe = eleventyConfig.getFilter("getReadMe")
  const latestCommit = repo.commits.get(ref.sha)
  const latestCommitMessage = latestCommit.message.length > 72
    ? latestCommit.message.split('\n')[0].substr(0, 72) + '...'
    : latestCommit.message

  const mostRecentCommitOverall = data.mostRecentCommitsOverall[repo.name]

  const nav = NavHelper({
    reposConfig,
    slugify,
    currentRepoName: repo.name,
    currentRefName: data.currentRef.name,
    currentRefType: data.flatRef.type,
  })

  const languageCounts = new Map<string, number>()

  const countPromises = Array.from(ref.fileList.keys()).map(async (currentFile) => {
    return new Promise<void>(async (resolve) => {
      const fileParts = currentFile.split(".")
      const fileExtension = fileParts[fileParts.length - 1]
// todo: add more ignoreable extensions or specific files
// (like package-lock.json). Allow glob patterns?
      if (fileExtension === 'gitignore') {
        resolve()
      }

      const fileLineCount = (await repo.files(currentFile, data.currentRef.sha)).contents.split('\n').length
      languageCounts.set(fileExtension, (languageCounts.get(fileExtension) + fileLineCount) || fileLineCount)
      resolve()
    })
  })

  await Promise.all(countPromises)

  let languagePercentages: Array<[string, number]> = []
  const total = Array.from(ref.fileList.keys()).length

  for (const entry of languageCounts) {
    languagePercentages.push([entry[0], entry[1] / total])
  }
  languagePercentages.sort((a, b) => {
    return b[1] - a[1]
  })

  // Show graph for the top 5 languages, unless there are fewer than 5 total
  const numOfTopLanguages = Math.min(5, languagePercentages.length)
  const topLanguagePercentages = languagePercentages.slice(0, numOfTopLanguages)
  const otherLanguagePercent = languagePercentages.slice(numOfTopLanguages).reduce((sum, current) => {
    return sum + current[1]
  }, 0)

  const largestPercent = Math.max(...topLanguagePercentages.map(tuple => tuple[1]), otherLanguagePercent)

  const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, ref.name), ref.name)
  // TODO: make dark mode work here
  const colors = reposConfig.defaultTemplate.colors.languageGraph

  const pageContent = [
    m('div', {class: "row"}, [
      m('div', {class: "col"}, [
        m('div', {class: "px-4 pt-3 bezel-header"}, [
          m('div', {class: "row"}, [
            m('div', {class: "col-12 col-lg-6"}, [
              m('h1', {class: "display-3 text-white"},
                m('em', repo.name)
              ),
              repo.description
                ? m('p', {class: "text-white fs-4 fw-light"}, repo.description)
                : null
            ]),
            m('div', {class: "col-12 col-lg-6 d-flex flex-column justify-content-around"}, [
              m('div', {class: 'row'}, [
                m('div', {class: "col-12 col-sm-6"}, [
                  m('div', {class: "row"}, [
                    m('div', {class: "col-6 col-lg-12 pb-0 pb-lg-2"}, [
                      m('div', {class: "text-white d-inline-block"}, [
                        m('div', {class: "latest-commit fs-6 fw-light"}, [
                          m('span', {class: 'me-1'}, `Latest in ${ref.name}`),
                          m('a', {href: nav.rssFeed(), class: "fw-light p-0 btn badge shadow-none"}, [
                            m('img', {
                              class: 'mb-1 me-1',
                              src: `${nav.rootPath()}frontend/img/rss-icon.svg`,
                              style: "width: 11px;"
                            }),
                            'RSS',
                          ]),
                        ]),
                        m('div', {class: "font-monospace"}, [
                          `${latestCommit.date.toDateString().split(' ').slice(1).join(' ')} `,
                          m('a', {href: nav.commit(latestCommit.hash), class: "fw-bold link-info"}, latestCommit.hash.substr(0, 6))
                        ]),
                      ])
                    ]),
                    m('div', {class: "col-6 col-lg-12 pb-3 pb-lg-0"}, [
                      m('div', {class: "text-white d-inline-block"}, [
                        m('div', {class: "latest-commit fs-6 fw-light"}, 'Latest overall'),
                        m('div', {class: "font-monospace"}, [
                          `${mostRecentCommitOverall.commit.date.toDateString().split(' ').slice(1).join(' ')} `,
                          m('a', {
                            href: nav.commit(mostRecentCommitOverall.commit.hash),
                            class: "link-info fw-bold"
                          }, mostRecentCommitOverall.commit.hash.substr(0, 6))
                        ]),
                        m('span', {class: "fs-6 fw-light"}, [
                          'in branch ',
                          m('a', {
                            href: nav.commits(1, {
                              refName: mostRecentCommitOverall.branch.name,
                              refType: 'branch',
                            }),
                            class: "link-info"
                          }, mostRecentCommitOverall.branch.name),
                        ])
                      ])
                    ])
                  ])
                ]),
                m('div', {class: "col-12 col-sm-6 d-flex"}, [
                  m('div', {class: "d-flex flex-column"}, [
                    topLanguagePercentages.map((percentTuple) => {
                      return m('div', {class: 'language-name me-1 d-flex justify-content-end align-items-end small text-white font-monospace flex-grow-1'}, percentTuple[0])
                    }),
                    otherLanguagePercent > 0
                    ? m('div', {class: 'language-name me-1 d-flex justify-content-end align-items-end small text-white font-monospace flex-grow-1'}, 'other')
                    : null
                  ]),
                  m('div', {class: "flex-grow-1 d-flex flex-column"}, [
                    topLanguagePercentages.map((percentTuple, index) => {
                      const color = colors[index % (colors.length - 1)].light
                      return m('div', {
                        class: 'language-col flex-grow-1',
                        style: `width: ${percentTuple[1] / largestPercent * 100}%; background-color: ${color};`
                      })
                    }),
                    otherLanguagePercent > 0
                      ? m('div', {
                        class: 'language-col flex-grow-1',
                        style: `width: ${otherLanguagePercent / largestPercent * 100}%; background-color: ${colors[colors.length - 1].light};`
                      })
                      : null
                  ])
                ]),
              ]),
              m('div', {class: "row align-items-center"}, [
                m('div', {class: "col-12"}, [
                  m('div', {class: "header-button-container"}, [
                    m('button', {class: "btn btn-info btn-lg dropdown-toggle clone-popover-btn"}, 'Clone'),
                    nav.homepageButtons.map((buttonConfig) => {
                      return m('a', {
                        class: "btn btn-outline-info btn-lg shadow-none",
                        href: buttonConfig.url,
                        target: buttonConfig.newTab ? "_blank" : "_self"
                      }, m.trust(buttonConfig.text + `${buttonConfig.newTab ? ' <span>&#x29C9;</span>' : ''}`))
                    })
                  ])
                ])
              ])
            ])
          ]),
          m('noscript',
            m('div', {class: "row mt-2"},
              m('div', {class: "col"},
                m('p', {class: "font-monospace text-white"},
                  `Clone URL: ${repo.cloneUrl}`
                )
              )
            )
          ),
        ])
      ])
    ]),
    m('div', {class: "row my-4 mx-1"},
      m('div', {class: "col readme"}, m.trust(readmeContent))
    )
  ]

  return await htmlPage(reposConfig, eleventyConfig, data, pageContent)
}
