import type * as Effect from "../Effect.js"
import { dual, pipe } from "../Function.js"
import * as Option from "../Option.js"
import type * as Synchronized from "../SynchronizedRef.js"
import * as core from "./core.js"
/** @internal */
export const getAndUpdateEffect = dual<
(f: (a: A) => Effect.Effect) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(self: Synchronized.SynchronizedRef, f: (a: A) => Effect.Effect) => Effect.Effect
>(2, (self, f) =>
self.modifyEffect(
(value) => core.map(f(value), (result) => [value, result] as const)
))
/** @internal */
export const getAndUpdateSomeEffect = dual<
(
pf: (a: A) => Option.Option>
) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(
self: Synchronized.SynchronizedRef,
pf: (a: A) => Option.Option>
) => Effect.Effect
>(2, (self, pf) =>
self.modifyEffect((value) => {
const result = pf(value)
switch (result._tag) {
case "None": {
return core.succeed([value, value] as const)
}
case "Some": {
return core.map(result.value, (newValue) => [value, newValue] as const)
}
}
}))
/** @internal */
export const modify = dual<
(f: (a: A) => readonly [B, A]) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(self: Synchronized.SynchronizedRef, f: (a: A) => readonly [B, A]) => Effect.Effect
>(2, (self, f) => self.modify(f))
/** @internal */
export const modifyEffect = dual<
(
f: (a: A) => Effect.Effect
) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(
self: Synchronized.SynchronizedRef,
f: (a: A) => Effect.Effect
) => Effect.Effect
>(2, (self, f) => self.modifyEffect(f))
/** @internal */
export const modifySomeEffect = dual<
(
fallback: B,
pf: (a: A) => Option.Option>
) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(
self: Synchronized.SynchronizedRef,
fallback: B,
pf: (a: A) => Option.Option>
) => Effect.Effect
>(3, (self, fallback, pf) =>
self.modifyEffect(
(value) => pipe(pf(value), Option.getOrElse(() => core.succeed([fallback, value] as const)))
))
/** @internal */
export const updateEffect = dual<
(
f: (a: A) => Effect.Effect
) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(self: Synchronized.SynchronizedRef, f: (a: A) => Effect.Effect) => Effect.Effect
>(2, (self, f) =>
self.modifyEffect((value) =>
core.map(
f(value),
(result) => [undefined as void, result] as const
)
))
/** @internal */
export const updateAndGetEffect = dual<
(f: (a: A) => Effect.Effect) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(self: Synchronized.SynchronizedRef, f: (a: A) => Effect.Effect) => Effect.Effect
>(2, (self, f) =>
self.modifyEffect(
(value) => core.map(f(value), (result) => [result, result] as const)
))
/** @internal */
export const updateSomeEffect = dual<
(
pf: (a: A) => Option.Option>
) => (self: Synchronized.SynchronizedRef) => Effect.Effect,
(
self: Synchronized.SynchronizedRef,
pf: (a: A) => Option.Option>
) => Effect.Effect
>(2, (self, pf) =>
self.modifyEffect((value) => {
const result = pf(value)
switch (result._tag) {
case "None": {
return core.succeed([void 0, value] as const)
}
case "Some": {
return core.map(result.value, (a) => [void 0, a] as const)
}
}
}))