const MAX_PAGE_MATERIALS = 16
const MATERIALS_PER_ROW = 4
const MAX_BLOCK_SIZE = 3

function chunkify(array, size) {
  let chunks = []
  for (let i = 0, j = array.length; i < j; i += size) {
    let slice = array.slice(i, i + size)
    chunks.push(slice)
  }
  return chunks
}

function copyModel(model) {
  if (model) {
    return JSON.parse(JSON.stringify(model))
  } else {
    console.error('no model to copy')
  }
}

function copyModels(models) {
  let copies = []

  if (models) {
    for (let model of models) {
      let copy = copyModel(model)
      copies.push(copy)
    }
  }

  return copies
}

// split models with too many materials
function splitModels(models) {
  let splits = []
  for (let model of models) {
    if (model.size > MAX_BLOCK_SIZE) {
      let chunks = chunkify(model.ids, MAX_PAGE_MATERIALS)
      for (let chunk of chunks) {
        let splitModel = copyModel(model)
        splitModel.ids = chunk
        splits.push(splitModel)
      }
    } else {
      splits.push(copyModel(model))
    }
  }
  return splits
}

// join adjacent models with the same model number
function joinModels(models) {
  let joins = []
  let lastModel = null
  for (let model of models) {
    model = copyModel(model)
    if (lastModel) {
      if (lastModel.model === model.model) {
        // match - join
        lastModel.ids.push(...model.ids)
        // uniquify
        lastModel.ids = lastModel.ids.filter((v, i, a) => a.indexOf(v) === i)
      } else {
        // no match - add
        joins.push(model)
        lastModel = model
      }
    } else {
      // first - add
      joins.push(model)
      lastModel = model
    }
  }
  return joins
}

export function paginateModels(models) {
  models = joinModels(models)

  for (let model of models) {
    model.size = modelBlockSize(model)
  }

  models = splitModels(models)

  for (let model of models) {
    model.size = modelBlockSize(model)
  }

  models = copyModels(models)

  let pages = []
  let currentSize = 0
  let currentPage = []
  for (let model of models) {
    if (model.size < 1) {
      // skip empty models
      continue
    }
    currentSize += model.size
    if (currentSize > 3) {
      pages.push(currentPage)
      currentPage = [model]
      currentSize = model.size
    } else {
      currentPage.push(model)
    }
  }
  if (currentPage.length > 0) {
    pages.push(currentPage)
  }

  return pages
}

export function modelBlockSize(model) {
  if (!model || !model.ids) return 0
  if (model.ids.length <= MATERIALS_PER_ROW) return 1
  if (model.ids.length <= MATERIALS_PER_ROW * 2) return 2
  if (model.ids.length <= MATERIALS_PER_ROW * 4) return 3
  return MAX_BLOCK_SIZE + 1 // generic "too big"
}

// de-paginate, essentially
export function modelsFromSection(section, getters) {
  // remove pages, return models (blocks) in order.
  // combine blocks with the same model number.
  let models = []
  if (section && section.pages) {
    for (let page of section.pages) {
      for (let model of page) {
        model = copyModel(model)
        if (model.ids && model.ids.length > 0) {
          // add extra info from a material
          let material = getters.material(model.ids[0])
          if (material) {
            model = extendModelFromMaterial(material, model)
          } else {
            console.log('no material found for id', model.ids[0])
          }
          models.push(model)
        }
      }
    }
  }
  return joinModels(models)
}

export function sectionTitle(material) {
  // "Trailhead (Men)"
  if (material) {
    return `${material.category} (${material.gender})`
  } else {
    return '(unknown)'
  }
}

// add properties from the material to the model,
// creating it if necessary.
export function extendModelFromMaterial(material, model = {}) {
  if (material) {
    if (!model['name']) {
      // don't overwrite possibly overridden value
      model['name'] = material.name
    }
    model['model'] = material.model
    model['family'] = material.family
    model['gender'] = material.gender
    model['category'] = material.category

    // make sure the material id is in the list
    let ids = model['ids'] || []
    if (!ids.includes(material.id)) {
      ids.push(material.id)
      model['ids'] = ids
    }
  }

  return model
}
