import { CommentSection } from '@/components/CommentSection'
import { Divider, Box, Space, Tabs, TabsList, TabsTab, TabsPanel, Code, Alert } from '@mantine/core'
import { IconInfoCircle } from '@tabler/icons-react'
import { NodeConfigGenerator } from '../components/cache/NodeConfigGenerator'
import { NodeQueryBuilder } from '../components/cache/NodeQueryBuilder'

# ResilientDB Node Cache

ResilientDB Node Cache is a TypeScript library that provides real-time synchronization between ResilientDB and MongoDB using WebSocket and HTTP connections. It's designed to be a robust caching layer for blockchain data, making it easier to work with ResilientDB data in Node.js applications.

## Interactive Tools

<Tabs defaultValue="config">
  <TabsList>
    <TabsTab value="config">Configuration Generator</TabsTab>
    <TabsTab value="query">Query Builder</TabsTab>
  </TabsList>

  <TabsPanel value="config">
    <Box my="md">
      <Alert icon={<IconInfoCircle size={16} />} title="Interactive Configuration" color="blue">
        Use this tool to generate your Node Cache configuration code. Adjust the parameters below and copy the generated code.
      </Alert>
      <NodeConfigGenerator />
    </Box>
  </TabsPanel>

  <TabsPanel value="query">
    <Box my="md">
      <Alert icon={<IconInfoCircle size={16} />} title="MongoDB Query Builder" color="blue">
        Build and test MongoDB queries for your cached blockchain data. The results will show sample data structure.
      </Alert>
      <NodeQueryBuilder />
    </Box>
  </TabsPanel>
</Tabs>

## Features

- Real-time synchronization via WebSocket and HTTP
- Automatic reconnection handling
- Configurable batch processing
- Event-driven architecture
- MongoDB querying capabilities
- TypeScript support with full type definitions

## Installation

The library can be installed via npm:

```bash
npm install resilient-node-cache
```

## Syncing Data from ResilientDB to MongoDB

Create a sync script to initialize and start the data synchronization from ResilientDB to MongoDB.

```typescript
import { WebSocketMongoSync } from 'resilient-node-cache';

// MongoDB Configuration
const mongoConfig = {
  uri: 'mongodb://localhost:27017',
  dbName: 'myDatabase',
  collectionName: 'myCollection',
};

// ResilientDB Configuration
const resilientDBConfig = {
  baseUrl: 'resilientdb://crow.resilientdb.com',
  httpSecure: true,
  wsSecure: true,
};

// Initialize the sync
const sync = new WebSocketMongoSync(mongoConfig, resilientDBConfig);

// Set up event handlers
sync.on('connected', () => {
  console.log('WebSocket connected.');
});

sync.on('data', (newBlocks) => {
  console.log('Received new blocks:', newBlocks);
});

sync.on('error', (error) => {
  console.error('Error:', error);
});

sync.on('closed', () => {
  console.log('Connection closed.');
});

// Start synchronization
(async () => {
  try {
    await sync.initialize();
    console.log('Synchronization initialized.');
  } catch (error) {
    console.error('Error during sync initialization:', error);
  }
})();
```

## Fetching Data by Public Key

After syncing, you can retrieve that data from MongoDB depending on your use case. Here's a sample script to retrieve all transactions associated with a specified public key:

```typescript
// fetchTransactionsWithPublicKey.js

const { MongoClient } = require('mongodb');

const mongoConfig = {
  uri: 'mongodb://localhost:27017',
  dbName: 'myDatabase',
  collectionName: 'myCollection',
};

// The publicKey for which to fetch transactions
const targetPublicKey = "8LUKr81SmkdDhuBNAHfH9C8G5m6Cye2mpUggVu61USbD";

(async () => {
  const client = new MongoClient(mongoConfig.uri);

  try {
    await client.connect();
    const db = client.db(mongoConfig.dbName);
    const collection = db.collection(mongoConfig.collectionName);

    console.log('Connected to MongoDB for fetching transactions.');

    // Create an index on transactions.value.inputs.owners_before for optimized querying
    const indexName = await collection.createIndex({ "transactions.value.inputs.owners_before": 1 });
    console.log(`Index created: ${indexName} on transactions.value.inputs.owners_before`);

    // Define aggregation pipeline to fetch all transactions for the specified publicKey in owners_before
    const pipeline = [
      { $unwind: "$transactions" },
      { $unwind: "$transactions.value.inputs" },
      { 
        $match: { 
          "transactions.value.inputs.owners_before": targetPublicKey 
        }
      },
      { $sort: { "transactions.value.asset.data.timestamp": -1 } },
      { $project: { transaction: "$transactions", _id: 0 } }
    ];

    const cursor = collection.aggregate(pipeline);
    const transactions = await cursor.toArray();

    if (transactions.length > 0) {
      console.log('Transactions with the specified publicKey in owners_before:', 
                  JSON.stringify(transactions, null, 2));
    } else {
      console.log(`No transactions found for publicKey: ${targetPublicKey}`);
    }
  } catch (error) {
    console.error('Error fetching transactions:', error);
  } finally {
    await client.close();
  }
})();
```

## Data Synchronization

The Node Cache library synchronizes data between ResilientDB and MongoDB in real-time. When new blocks are received from ResilientDB:

1. The data is automatically stored in your configured MongoDB collection
2. The `data` event is emitted with the new blocks
3. You can query the data using standard MongoDB queries

The exact structure of the data in MongoDB will match the structure of blocks in your ResilientDB node. This ensures that your cached data remains consistent with the source.

## Best Practices

<Alert icon={<IconInfoCircle size={16} />} title="Performance Tips" color="blue">
  - Use appropriate indexes on your MongoDB collections
  - Configure batch sizes based on your data volume
  - Implement proper error handling and reconnection logic
  - Monitor WebSocket connection health
</Alert>

## API Reference

### WebSocketMongoSync Class

The main class for managing synchronization between ResilientDB and MongoDB.

#### Constructor
```typescript
new WebSocketMongoSync(mongoConfig: MongoConfig, resilientDBConfig: ResilientDBConfig)
```

#### Methods
- `initialize(): Promise<void>` - Start the synchronization process
- `close(): Promise<void>` - Close all connections and stop synchronization

#### Events
- `connected` - Fired when WebSocket connection is established
- `closed` - Fired when connection is closed
- `data` - Fired when new blocks are received
- `error` - Fired when an error occurs

<Space h="xl" />
<Divider my="xl" label="Community Feedback" labelPosition="center" />

<Box mb="xl">
  <CommentSection
    pageTitle="Python Cache Documentation"
    pageUrl={typeof window !== 'undefined' ? window.location.href : ''}
    repoOwner="apache"
    repoName="incubator-resilientdb-resilient-python-cache"
    labels={['user-feedback', 'documentation', 'python-cache']}
    title="Questions or Feedback about the Python Cache?"
  />
</Box> 