/*
 * dselect - Debian package maintenance user interface
 * pkgsublist.cc - status modification and recursive package list handling
 *
 * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <config.h>
#include <compat.h>

#include <assert.h>
#include <string.h>
#include <stdio.h>

#include <dpkg/i18n.h>
#include <dpkg/dpkg.h>
#include <dpkg/dpkg-db.h>

#include "dselect.h"
#include "bindings.h"

void packagelist::add(pkginfo *pkg) {
  debug(dbg_general, "packagelist[%p]::add(pkginfo %s)", this, pkg->name);
  if (!recursive ||  // never add things to top level
      !pkg->clientdata ||  // don't add pure virtual packages
      pkg->clientdata->uprec)  // don't add ones already in the recursive list
    return;
  debug(dbg_general, "packagelist[%p]::add(pkginfo %s) adding",
        this, pkg->name);
  perpackagestate *state= &datatable[nitems];
  state->pkg= pkg;
  state->direct= state->original= pkg->clientdata->selected;
  state->suggested= state->selected= pkg->clientdata->selected;
  state->spriority= sp_inherit; state->dpriority= dp_none;
  state->uprec= pkg->clientdata;
  state->relations.init();
  pkg->clientdata= state;
  table[nitems]= state;
  nitems++;
}

void packagelist::add(pkginfo *pkg, pkginfo::pkgwant nw) {
  debug(dbg_general, "packagelist[%p]::add(pkginfo %s, %s)",
        this, pkg->name, wantstrings[nw]);
  add(pkg);  if (!pkg->clientdata) return;
  pkg->clientdata->direct= nw;
  selpriority np;
  np= would_like_to_install(nw,pkg) ? sp_selecting : sp_deselecting;
  if (pkg->clientdata->spriority > np) return;
  debug(dbg_general, "packagelist[%p]::add(pkginfo %s, %s) setting",
        this, pkg->name, wantstrings[nw]);
  pkg->clientdata->suggested= pkg->clientdata->selected= nw;
  pkg->clientdata->spriority= np;
}

void packagelist::add(pkginfo *pkg, const char *extrainfo, showpriority showimp) {
  debug(dbg_general, "packagelist[%p]::add(pkginfo %s, ..., showpriority %d)",
        this, pkg->name, showimp);
  add(pkg);  if (!pkg->clientdata) return;
  if (pkg->clientdata->dpriority < showimp) pkg->clientdata->dpriority= showimp;
  pkg->clientdata->relations(extrainfo);
  pkg->clientdata->relations.terminate();
}

bool
packagelist::alreadydone(doneent **done, void *check)
{
  doneent *search = *done;

  while (search && search->dep != check)
    search = search->next;
  if (search)
    return true;
  debug(dbg_general, "packagelist[%p]::alreadydone(%p, %p) new",
        this, done, check);
  search= new doneent;
  search->next= *done;
  search->dep= check;
  *done= search;
  return false;
}

void packagelist::addunavailable(deppossi *possi) {
  debug(dbg_general, "packagelist[%p]::addunavail(%p)", this, possi);

  if (!recursive) return;
  if (alreadydone(&unavdone,possi)) return;

  assert(possi->up->up->clientdata);
  assert(possi->up->up->clientdata->uprec);

  varbuf& vb= possi->up->up->clientdata->relations;
  vb(possi->ed->name);
  vb(_(" does not appear to be available\n"));
}

bool
packagelist::add(dependency *depends, showpriority displayimportance)
{
  debug(dbg_general, "packagelist[%p]::add(dependency[%p])", this, depends);

  if (alreadydone(&depsdone, depends))
    return false;

  const char *comma= "";
  varbuf info;
  info(depends->up->name);
  info(' ');
  info(gettext(relatestrings[depends->type]));
  info(' ');
  deppossi *possi;
  for (possi=depends->list;
       possi;
       possi=possi->next, comma=(possi && possi->next ? ", " : _(" or "))) {
    info(comma);
    info(possi->ed->name);
    if (possi->verrel != dvr_none) {
      switch (possi->verrel) {
      case dvr_earlierequal:  info(" (<= "); break;
      case dvr_laterequal:    info(" (>= "); break;
      case dvr_earlierstrict: info(" (<< "); break;
      case dvr_laterstrict:   info(" (>> "); break;
      case dvr_exact:         info(" (= "); break;
      default: internerr("unknown verrel");
      }
      info(versiondescribe(&possi->version, vdew_nonambig));
      info(")");
    }
  }
  info('\n');
  add(depends->up,info.string(),displayimportance);
  for (possi=depends->list; possi; possi=possi->next) {
    add(possi->ed,info.string(),displayimportance);
    if (possi->verrel == dvr_none && depends->type != dep_provides) {
      // providers aren't relevant if a version was specified, or
      // if we're looking at a provider relationship already
      deppossi *provider;
      for (provider = possi->ed->available.depended;
           provider;
           provider = provider->rev_next) {
        if (provider->up->type != dep_provides) continue;
        add(provider->up->up,info.string(),displayimportance);
        add(provider->up,displayimportance);
      }
    }
  }
  return true;
}

void repeatedlydisplay(packagelist *sub,
                       showpriority initial,
                       packagelist *unredisplay) {
  pkginfo **newl;
  keybindings *kb;

  debug(dbg_general, "repeatedlydisplay(packagelist[%p])", sub);
  if (sub->resolvesuggest() != 0 && sub->deletelessimp_anyleft(initial)) {
    debug(dbg_general, "repeatedlydisplay(packagelist[%p]) once", sub);
    if (unredisplay) unredisplay->enddisplay();
    for (;;) {
      manual_install = 0; /* Remove flag now that resolvesuggest has seen it. */
      newl= sub->display();
      if (!newl) break;
      debug(dbg_general, "repeatedlydisplay(packagelist[%p]) newl", sub);
      kb= sub->bindings; delete sub;
      sub= new packagelist(kb,newl);
      if (sub->resolvesuggest() <= 1) break;
      if (!sub->deletelessimp_anyleft(dp_must)) break;
      debug(dbg_general, "repeatedlydisplay(packagelist[%p]) again", sub);
    }
    if (unredisplay) unredisplay->startdisplay();
  }
  debug(dbg_general, "repeatedlydisplay(packagelist[%p]) done", sub);
  delete sub;
}

int packagelist::deletelessimp_anyleft(showpriority than) {
  debug(dbg_general, "packagelist[%p]::dli_al(%d): nitems=%d",
        this, than, nitems);
  int insat, runthr;
  for (runthr=0, insat=0;
       runthr < nitems;
       runthr++) {
    if (table[runthr]->dpriority < than) {
      table[runthr]->free(recursive);
    } else {
      if (insat != runthr) table[insat]= table[runthr];
      insat++;
    }
  }
  nitems= insat;
  debug(dbg_general, "packagelist[%p]::dli_al(%d) done; nitems=%d",
        this, than, nitems);
  return nitems;
}
