// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "modules/buttons/manager.h"
#define PW_LOG_MODULE_NAME "BUTTONS"

#include "pw_assert/check.h"
#include "pw_log/log.h"
#include "pw_status/try.h"

using pw::chrono::SystemClock;
using pw::digital_io::DigitalIn;
using pw::digital_io::State;

namespace sense {
State Debouncer::UpdateState(SystemClock::time_point now, State state) {
  if (state != last_input_) {
    last_update_ = now;
    last_input_ = state;
  } else if (now - last_update_ >= kDebounceInterval) {
    output_ = state;
  }

  return output_;
}

EdgeDetector::StateChange EdgeDetector::UpdateState(State state) {
  auto prev_state = current_state_;
  current_state_ = state;

  if (prev_state == State::kInactive && current_state_ == State::kActive) {
    return StateChange::kActivate;
  }
  if (prev_state == State::kActive && current_state_ == State::kInactive) {
    return StateChange::kDeactivate;
  }
  return StateChange::kNone;
}

pw::Result<EdgeDetector::StateChange> Button::Sample(
    SystemClock::time_point now) {
  PW_TRY_ASSIGN(auto raw_state, io_.GetState());
  auto deboucned_state = debouncer_.UpdateState(now, raw_state);
  return edge_detector_.UpdateState(deboucned_state);
}

ButtonManager::ButtonManager(pw::digital_io::DigitalIn& button_a,
                pw::digital_io::DigitalIn& button_b,
                pw::digital_io::DigitalIn& button_x,
                pw::digital_io::DigitalIn& button_y) : buttons_{
                  Button(button_a),
                  Button(button_b),
                  Button(button_x),
                  Button(button_y),
                }
    , timer_(pw::bind_member<&ButtonManager::SampleCallback>(this)), active_(false) {}

ButtonManager::~ButtonManager() {}

void ButtonManager::Init(PubSub& pub_sub, Worker& worker) {
  pub_sub_ = &pub_sub;
  worker_ = &worker;

  // Start the periodic sampling callbacks.
  Start();
}

void ButtonManager::SampleCallback(SystemClock::time_point now) {
  PW_CHECK_NOTNULL(worker_);
  worker_->RunOnce([this, now]() {
    if (const auto status = SampleButtons(now); !status.ok()) {
      PW_LOG_ERROR("Failed to sample buttons: %s", status.str());
    }
    // Start the periodic sampling callbacks.
    timer_.InvokeAfter(kSampleInterval);
  });
}

template <typename ButtonEvent>
pw::Status ButtonManager::SampleButton(Button& button,
                                       SystemClock::time_point now) {
  PW_TRY_ASSIGN(auto state_change, button.Sample(now));
  if (state_change == EdgeDetector::StateChange::kActivate) {
    std::ignore = pub_sub_->Publish(ButtonEvent(true));
  } else if (state_change == EdgeDetector::StateChange::kDeactivate) {
    std::ignore = pub_sub_->Publish(ButtonEvent(false));
  }
  return pw::OkStatus();
}

pw::Status ButtonManager::SampleButtons(SystemClock::time_point now) {
  PW_TRY(SampleButton<sense::ButtonA>(buttons_[0], now));
  PW_TRY(SampleButton<sense::ButtonB>(buttons_[1], now));
  PW_TRY(SampleButton<sense::ButtonX>(buttons_[2], now));
  PW_TRY(SampleButton<sense::ButtonY>(buttons_[3], now));
  return pw::OkStatus();
}

}  // namespace sense
