import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/functional/en/Classes/CacheItem'/>

# CacheItem Class

Low-level class for managing a single caching value with automatic invalidation based on comparison data. This class is used internally by the Cache class but can also be used directly for fine-grained cache control.

## Key Features

- **Single value caching** — manages one cached value with intelligent invalidation
- **Comparison-based invalidation** — automatically invalidates cache when comparison data changes
- **Previous value tracking** — maintains reference to old cached value during updates
- **Synchronous and asynchronous support** — both sync and async callback execution
- **Type safety** — full TypeScript support with generics
- **Memory efficient** — minimal overhead for single value storage

## Constructor

### `constructor`

Creates a new CacheItem instance with the provided callback function.

**Parameters:**
- `callback: () => T` — function to execute when cache needs to be generated or updated

```javascript
import { CacheItem } from '@dxtmisha/functional'

// Simple cache item for expensive computation
const expensiveComputation = new CacheItem(() => {
  console.log('Performing expensive computation...')
  return Math.random() * 1000
})

// Cache item for API data
const apiData = new CacheItem(() => {
  console.log('Fetching from API...')
  return fetch('/api/data').then(r => r.json())
})
```

## Data Retrieval Methods

### `getCache`

Gets cached data or executes callback to generate new data if cache is invalid.

**Parameters:**
- `comparison: any[]` — array of values used for cache invalidation comparison

**Returns:** `T` — cached data or result of callback execution

```javascript
const userCache = new CacheItem(() => {
  console.log('Loading user data...')
  return { id: 1, name: 'John Doe', role: 'admin' }
})

let userId = 1
let userRole = 'admin'

// First call - executes callback
const user1 = userCache.getCache([userId, userRole])
console.log(user1) // Logs: "Loading user data..." then returns user object

// Second call with same comparison - returns cached data
const user1Cached = userCache.getCache([userId, userRole])
console.log(user1Cached) // Returns cached data without logging

// Change comparison data - cache invalidated
userId = 2
const user2 = userCache.getCache([userId, userRole])
console.log(user2) // Logs: "Loading user data..." then returns new user object
```

### `getCacheAsync`

Asynchronously gets cached data or executes async callback to generate new data.

**Parameters:**
- `comparison: any[]` — array of values used for cache invalidation comparison

**Returns:** `Promise<T>` — promise resolving to cached data or callback result

```javascript
const apiCache = new CacheItem(async () => {
  console.log('Fetching user from API...')
  const response = await fetch('/api/user/1')
  return await response.json()
})

// First call - executes async callback
const user = await apiCache.getCacheAsync([])
console.log(user) // Logs: "Fetching user from API..." then returns user data

// Second call - returns cached data
const userCached = await apiCache.getCacheAsync([])
console.log(userCached) // Returns cached data without API call
```

### `getCacheOld`

Returns the previous cached value (before last update).

**Returns:** `T | undefined` — previous cached value or undefined if no previous value

```javascript
const dataCache = new CacheItem(() => ({ timestamp: Date.now() }))

// Get initial data
const data1 = dataCache.getCache(['v1'])
console.log(dataCache.getCacheOld()) // undefined (no previous value)

// Update cache with new comparison
const data2 = dataCache.getCache(['v2'])
console.log(dataCache.getCacheOld()) // Returns data1 (previous value)

// Update again
const data3 = dataCache.getCache(['v3'])
console.log(dataCache.getCacheOld()) // Returns data2 (previous value)
```

## Practical Examples

### Computation Caching

```javascript
const expensiveCache = new CacheItem(() => {
  console.log('Performing expensive computation...')
  return Array.from({length: 1000000}, (_, i) => i * i).reduce((a, b) => a + b)
})

let factor = 1
let data = [1, 2, 3]

// First call
const result1 = expensiveCache.getCache([factor, data])
console.log('Result:', result1)

// Cached call
const result2 = expensiveCache.getCache([factor, data])
console.log('Cached:', result2) // No recalculation
```

### Validation with History

```javascript
const validationCache = new CacheItem(() => {
  const errors = []
  if (!this.value) errors.push('Field required')
  if (this.value.length < 3) errors.push('Minimum 3 characters')
  return { isValid: errors.length === 0, errors }
})

function validateField(value) {
  this.value = value
  const current = validationCache.getCache([value])
  const previous = validationCache.getCacheOld()

  return { current, previous, hasChanged: previous && current !== previous }
}

// Usage
console.log(validateField('ab')) // Shows errors
console.log(validateField('abc')) // Valid result
```

### Async Data

```javascript
const apiCache = new CacheItem(async () => {
  const response = await fetch('/api/data')
  return response.json()
})

async function getData(userId) {
  return await apiCache.getCacheAsync([userId])
}

// Usage
const data = await getData(1) // API call
const cached = await getData(1) // Cached data
```

The CacheItem class provides low-level control over caching a single value with powerful invalidation capabilities and change history tracking.
