// Copyright 2026 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.

use foreign_box::ForeignBox;
use pw_status::{Error, Result};
use syscall_defs::ExitStatus;

use crate::Kernel;
use crate::object::{KernelObject, ObjectBase, Signals};
use crate::scheduler::thread::{ProcessHandle, Thread, ThreadHandle};
use crate::scheduler::{SchedulerState, TryJoinResult};
use crate::sync::spinlock::{SpinLock, SpinLockGuard};

enum State<K: Kernel> {
    Stopped(ForeignBox<Thread<K>>),
    Running(ThreadHandle<K>),
    Empty,
}

impl<K: Kernel> State<K> {
    fn take_thread(&mut self) -> Option<ForeignBox<Thread<K>>> {
        match core::mem::replace(self, State::Empty) {
            State::Stopped(thread) => Some(thread),
            state => {
                *self = state;
                None
            }
        }
    }
}

pub struct ThreadObject<K: Kernel> {
    base: ObjectBase<K>,
    state: SpinLock<K, State<K>>,
}

impl<K: Kernel> ThreadObject<K> {
    #[must_use]
    pub const fn new(thread: ForeignBox<Thread<K>>) -> Self {
        Self {
            base: ObjectBase::new(Signals::no_active()),
            state: SpinLock::new(State::Stopped(thread)),
        }
    }

    pub const fn new_empty() -> Self {
        Self {
            base: ObjectBase::new(Signals::no_active()),
            state: SpinLock::new(State::Empty),
        }
    }

    pub fn set_thread(&self, kernel: K, thread: ForeignBox<Thread<K>>) -> Result<()> {
        let mut state = self.state.lock(kernel);
        match *state {
            State::Empty => {
                *state = State::Stopped(thread);
                Ok(())
            }
            _ => Err(Error::AlreadyExists),
        }
    }

    pub fn start(
        &self,
        kernel: K,
        process_handle: ProcessHandle<K>,
        initial_pc: usize,
        initial_sp: usize,
        args: (usize, usize, usize),
    ) -> Result<()> {
        let mut state = self.state.lock(kernel);
        let Some(mut thread) = state.take_thread() else {
            return Err(Error::AlreadyExists);
        };

        // SAFETY: `ThreadObject` is a kernel object that is always managed
        // within a `ForeignRcState` (e.g., when wrapped in `ForeignRc` or
        // `ForeignBox` for the object table). Thus, the `&self` reference
        // points to storage contained inside a `ForeignRcState`.
        let self_rc = unsafe { foreign_box::ForeignRcState::create_ref_from_inner(self) };
        thread.object = Some(self_rc.clone());

        unsafe {
            thread.initialize_non_priv_thread(
                kernel,
                process_handle,
                initial_pc,
                initial_sp,
                args,
            )?;
        }
        let thread_handle = crate::scheduler::start_thread(kernel, thread);
        *state = State::Running(thread_handle);
        Ok(())
    }

    pub fn terminate(&self, kernel: K) -> Result<()> {
        let mut thread_handle = {
            let state = self.state.lock(kernel);
            match &*state {
                State::Running(thread_handle) => thread_handle.clone(),
                State::Stopped(_) => return Err(Error::FailedPrecondition),
                State::Empty => return Err(Error::Internal),
            }
        };
        // Call terminate without holding the state lock
        thread_handle.terminate(kernel, ExitStatus::TerminatedBySyscall)
    }

    pub fn join_locked<'a>(
        &self,
        kernel: K,
        sched: SpinLockGuard<'a, K, SchedulerState<K>>,
    ) -> (SpinLockGuard<'a, K, SchedulerState<K>>, Result<ExitStatus>) {
        let thread_handle = {
            let mut state = self.state.lock(kernel);
            match core::mem::replace(&mut *state, State::Empty) {
                State::Running(t) => t,
                old_state => {
                    *state = old_state;
                    return (sched, Err(Error::FailedPrecondition));
                }
            }
        };

        let res = thread_handle.try_join_locked(kernel, sched);

        match res {
            (sched, crate::scheduler::TryJoinResult::Joined(thread, status)) => {
                let mut state = self.state.lock(kernel);
                *state = State::Stopped(thread);
                (sched, Ok(status))
            }
            (sched, crate::scheduler::TryJoinResult::Wait(thread_handle)) => {
                let mut state = self.state.lock(kernel);
                *state = State::Running(thread_handle);
                (sched, Err(Error::Unavailable))
            }
            (
                sched,
                TryJoinResult::Err {
                    error,
                    thread: thread_handle,
                },
            ) => {
                let mut state = self.state.lock(kernel);
                *state = State::Running(thread_handle);
                (sched, Err(error))
            }
        }
    }

    pub(crate) fn signal_locked<'a, F: Fn(Signals) -> Signals>(
        &self,
        kernel: K,
        sched: SpinLockGuard<'a, K, SchedulerState<K>>,
        update_fn: F,
    ) -> SpinLockGuard<'a, K, SchedulerState<K>> {
        self.base.signal_locked(kernel, sched, update_fn)
    }
}

impl<K: Kernel> KernelObject<K> for ThreadObject<K> {
    fn base(&self) -> Option<&ObjectBase<K>> {
        Some(&self.base)
    }

    fn object_wait(
        &self,
        kernel: K,
        signal_mask: Signals,
        deadline: time::Instant<K::Clock>,
    ) -> Result<crate::object::WaitReturn> {
        self.base.wait_until(kernel, signal_mask, deadline)
    }

    fn thread_start(&self, kernel: K, initial_pc: usize, initial_sp: usize) -> Result<()> {
        let process = kernel.get_scheduler().lock(kernel).current_process_handle();
        self.start(kernel, process.clone(), initial_pc, initial_sp, (0, 0, 0))
    }

    fn task_terminate(&self, kernel: K) -> Result<()> {
        self.terminate(kernel)
    }

    fn task_join(&self, kernel: K) -> Result<ExitStatus> {
        let sched = kernel.get_scheduler().lock(kernel);
        let (_, res) = self.join_locked(kernel, sched);
        res
    }
}
