// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>

#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <fbl/array.h>

#include "binding_internal.h"
#include "coordinator.h"
#include "device.h"
#include "src/devices/lib/log/log.h"

namespace internal {

uint32_t LookupBindProperty(BindProgramContext* ctx, uint32_t id) {
  for (const auto prop : *ctx->props) {
    if (prop.id == id) {
      return prop.value;
    }
  }

  // fallback for devices without properties
  switch (id) {
    case BIND_PROTOCOL:
      return ctx->protocol_id;
    case BIND_AUTOBIND:
      return ctx->autobind;
    default:
      // TODO: better process for missing properties
      return 0;
  }
}

bool EvaluateBindProgram(BindProgramContext* ctx) {
  const zx_bind_inst_t* ip = ctx->binding;
  const zx_bind_inst_t* end = ip + (ctx->binding_size / sizeof(zx_bind_inst_t));
  uint32_t flags = 0;

  while (ip < end) {
    uint32_t inst = ip->op;
    bool cond;

    if (BINDINST_CC(inst) != COND_AL) {
      uint32_t value = ip->arg;
      uint32_t pid = BINDINST_PB(inst);
      uint32_t pval;
      if (pid != BIND_FLAGS) {
        pval = LookupBindProperty(ctx, pid);
      } else {
        pval = flags;
      }

      // evaluate condition
      switch (BINDINST_CC(inst)) {
        case COND_EQ:
          cond = (pval == value);
          break;
        case COND_NE:
          cond = (pval != value);
          break;
        case COND_LT:
          cond = (pval < value);
          break;
        case COND_GT:
          cond = (pval > value);
          break;
        case COND_LE:
          cond = (pval <= value);
          break;
        case COND_GE:
          cond = (pval >= value);
          break;
        default:
          // illegal instruction: abort
          LOGF(ERROR, "Driver '%s' has illegal bind instruction %#08x", ctx->name, inst);
          return false;
      }
    } else {
      cond = true;
    }

    if (cond) {
      switch (BINDINST_OP(inst)) {
        case OP_ABORT:
          return false;
        case OP_MATCH:
          return true;
        case OP_GOTO: {
          uint32_t label = BINDINST_PA(inst);
          while (++ip < end) {
            if ((BINDINST_OP(ip->op) == OP_LABEL) && (BINDINST_PA(ip->op) == label)) {
              goto next_instruction;
            }
          }
          LOGF(ERROR, "Driver '%s' illegal GOTO", ctx->name);
          return false;
        }
        case OP_LABEL:
          // no op
          break;
        default:
          // illegal instruction: abort
          LOGF(ERROR, "Driver '%s' illegal bind instruction %#08x", ctx->name, inst);
          return false;
      }
    }

  next_instruction:
    ip++;
  }

  // default if we leave the program is no-match
  return false;
}

Match SumMatchCounts(Match m1, Match m2) {
  switch (m1) {
    case Match::None:
      return m2;
    case Match::One:
      return (m2 == Match::None ? Match::One : Match::Many);
    case Match::Many:
      return Match::Many;
  }
  __builtin_trap();
}

// Instantiate MatchParts<Device>
template Match MatchParts(const fbl::RefPtr<Device>& device, const FragmentPartDescriptor* parts,
                          uint32_t parts_count);

}  // namespace internal

bool driver_is_bindable(const Driver* drv, uint32_t protocol_id,
                        const fbl::Array<const zx_device_prop_t>& props, bool autobind) {
  internal::BindProgramContext ctx;
  ctx.props = &props;
  ctx.protocol_id = protocol_id;
  ctx.binding = drv->binding.get();
  ctx.binding_size = drv->binding_size;
  ctx.name = drv->name.c_str();
  ctx.autobind = autobind ? 1 : 0;
  return internal::EvaluateBindProgram(&ctx);
}
