# Contributing to OCG (OpenCypher Graph)

Thank you for your interest in contributing to OCG! 🎉

This document provides guidelines for contributing to the project.

## Table of Contents

- [Development Setup](#development-setup)
- [Running Tests](#running-tests)
- [Code Style](#code-style)
- [Pull Request Process](#pull-request-process)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Features](#suggesting-features)
- [Project Structure](#project-structure)
- [Release Process](#release-process)

## Development Setup

### Prerequisites

- **Rust** 1.70+ (install via [rustup](https://rustup.rs/))
  ```bash
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  rustup update stable
  ```

- **Python** 3.8+ (for Python bindings)
  ```bash
  # macOS
  brew install python@3.11

  # Ubuntu/Debian
  sudo apt install python3.11 python3.11-dev

  # Windows
  # Download from python.org
  ```

- **Git**
  ```bash
  # macOS
  brew install git

  # Ubuntu/Debian
  sudo apt install git
  ```

### Clone and Build

```bash
# Clone repository
git clone https://github.ibm.com/enjoycode/nxcypher-networkit.git
cd nxcypher-networkit

# Build all features
cargo build --all-features

# Run tests
cargo test --all-features

# Build release version
cargo build --release --all-features
```

### Python Development

For working on Python bindings:

```bash
# Install maturin (build tool for PyO3)
pip install maturin

# Build and install locally (development mode)
maturin develop --features python

# Test Python import
python3 -c "import ocg; print(ocg.__version__)"

# Build wheel
maturin build --release --features python --out dist/

# Install wheel
pip install dist/*.whl
```

### IDE Setup

#### VS Code
Recommended extensions:
- `rust-lang.rust-analyzer` - Rust language support
- `tamasfe.even-better-toml` - TOML file support
- `ms-python.python` - Python support

Recommended settings (`.vscode/settings.json`):
```json
{
  "rust-analyzer.checkOnSave.command": "clippy",
  "rust-analyzer.cargo.features": "all",
  "editor.formatOnSave": true,
  "[rust]": {
    "editor.defaultFormatter": "rust-lang.rust-analyzer"
  }
}
```

#### IntelliJ IDEA / CLion
- Install "Rust" plugin
- Install "Python" plugin
- Enable "Reformat on save"

## Running Tests

### Rust Tests

```bash
# All tests
cargo test --all-features

# Unit tests only
cargo test --lib

# Integration tests
cargo test --test '*'

# Specific test file
cargo test --test tck_property_graph

# Specific test
cargo test test_create_node

# With output
cargo test -- --nocapture

# Without Python features (faster)
cargo test --no-default-features
```

### openCypher TCK Tests

```bash
# Run full TCK suite (3,874 scenarios)
cargo test --test tck_property_graph

# Run with verbose output
cargo test --test tck_property_graph -- --nocapture

# Expected: 3,851/3,874 pass (99.0%)
```

### Python TCK Tests

```bash
# Install behave
pip install behave

# Run all Python TCK tests
cd tests/tck
python3 -m behave features/

# Run specific feature
python3 -m behave features/expressions/boolean/Boolean1.feature

# With verbose output
python3 -m behave features/ --verbose
```

### Benchmark Tests

```bash
# Run all benchmarks
cargo bench

# Specific benchmark
cargo bench --bench comparison

# Save baseline
cargo bench -- --save-baseline main

# Compare with baseline
cargo bench -- --baseline main
```

## Code Style

### Rust

**Formatting**: Use `rustfmt`
```bash
# Format all code
cargo fmt

# Check formatting without modifying
cargo fmt --check
```

**Linting**: Use `clippy`
```bash
# Run clippy
cargo clippy --all-features

# Fail on warnings
cargo clippy --all-features -- -D warnings

# Fix automatically (when possible)
cargo clippy --fix --all-features
```

**Documentation**: Add rustdoc comments to all public items
```rust
/// Creates a new node in the graph.
///
/// # Arguments
///
/// * `labels` - Vector of label strings
/// * `properties` - Map of property names to values
///
/// # Returns
///
/// The unique ID of the created node.
///
/// # Examples
///
/// ```
/// use ocg::PropertyGraph;
/// let mut graph = PropertyGraph::new();
/// let node_id = graph.create_node(vec!["Person".to_string()], HashMap::new());
/// ```
pub fn create_node(&mut self, labels: Vec<String>, properties: HashMap<String, CypherValue>) -> u64 {
    // implementation
}
```

**Error Handling**: Prefer `Result<T, E>` over `unwrap()`
```rust
// ❌ Avoid
let value = map.get(&key).unwrap();

// ✅ Prefer
let value = map.get(&key)
    .ok_or(ExecutionError::KeyNotFound(key.to_string()))?;

// Or with context
let value = map.get(&key)
    .ok_or_else(|| ExecutionError::NodeNotFound(id))?;
```

**Naming Conventions**:
- Types: `PascalCase`
- Functions/variables: `snake_case`
- Constants: `SCREAMING_SNAKE_CASE`
- Modules: `snake_case`

### Python

**Style**: Follow PEP 8
```bash
# Install formatters
pip install black isort

# Format code
black python/
isort python/
```

**Type Hints**: Add type annotations
```python
from typing import Dict, List, Optional

def execute(query: str, params: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
    """Execute an openCypher query."""
    pass
```

**Docstrings**: Use Google-style docstrings
```python
def execute(query: str, params: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
    """Execute an openCypher query.

    Args:
        query: The openCypher query string
        params: Optional query parameters

    Returns:
        List of result rows as dictionaries

    Raises:
        SyntaxError: If query has syntax errors
        ExecutionError: If query fails during execution

    Examples:
        >>> graph = Graph()
        >>> result = graph.execute("MATCH (n) RETURN n")
        >>> print(len(result))
        0
    """
    pass
```

## Pull Request Process

### 1. Fork and Branch

```bash
# Fork the repository on GitHub
# Then clone your fork
git clone https://github.com/YOUR_USERNAME/ocg.git
cd ocg

# Add upstream remote
git remote add upstream https://github.ibm.com/enjoycode/nxcypher-networkit.git

# Create feature branch
git checkout -b feature/amazing-feature
```

### 2. Make Changes

- Write code following style guidelines
- Add tests for new functionality
- Update documentation
- Ensure all tests pass

### 3. Commit Changes

Follow [Conventional Commits](https://www.conventionalcommits.org/):

```bash
# Format: <type>(<scope>): <description>

git commit -m "feat(parser): add support for UNION queries"
git commit -m "fix(executor): handle null values in aggregations"
git commit -m "docs(readme): update installation instructions"
git commit -m "test(tck): add tests for temporal functions"
git commit -m "refactor(backend): simplify node creation"
```

**Types**:
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation changes
- `test`: Test changes
- `refactor`: Code refactoring
- `perf`: Performance improvements
- `chore`: Maintenance tasks

### 4. Pre-PR Checklist

Before opening a PR, ensure:

- [ ] **Code compiles**: `cargo build --all-features`
- [ ] **All tests pass**: `cargo test --all-features`
- [ ] **No clippy warnings**: `cargo clippy --all-features -- -D warnings`
- [ ] **Code formatted**: `cargo fmt --check`
- [ ] **Documentation updated** (if needed)
- [ ] **CHANGELOG.md updated** (for non-trivial changes)
- [ ] **TCK compliance maintained**: 99.0%+ (3,851+ scenarios)
- [ ] **Commit messages follow convention**

```bash
# Run all checks
cargo fmt --check && \
cargo clippy --all-features -- -D warnings && \
cargo test --all-features && \
cargo test --test tck_property_graph
```

### 5. Push and Open PR

```bash
# Push to your fork
git push origin feature/amazing-feature

# Open PR on GitHub
# Fill in the PR template
```

### 6. PR Review

- Address reviewer feedback
- Keep PR focused (one feature/fix per PR)
- Squash commits if requested
- Be patient and respectful

### 7. Merge

- Maintainer will merge after approval
- Delete your feature branch after merge

## Reporting Bugs

### Before Reporting

1. **Check existing issues**: Search for similar bugs
2. **Update to latest**: Ensure bug exists in latest version
3. **Minimal reproduction**: Create smallest example that reproduces issue

### Bug Report Template

Open an issue with:

**Title**: Short, descriptive title

**Environment**:
- OS: Ubuntu 22.04
- Rust version: 1.70.0
- Python version: 3.11.5 (if relevant)
- OCG version: 0.1.0

**Description**: Clear description of the bug

**To Reproduce**:
```python
from ocg import Graph

graph = Graph()
# Minimal code that reproduces the bug
```

**Expected behavior**: What should happen

**Actual behavior**: What actually happens

**Error message** (if any):
```
Error: ...
```

**Additional context**: Any other relevant information

## Suggesting Features

### Before Suggesting

1. **Check existing issues**: Feature may already be requested
2. **Check openCypher spec**: Ensure feature aligns with specification
3. **Consider alternatives**: Think about different approaches

### Feature Request Template

Open an issue with:

**Title**: Short feature description

**Problem**: What problem does this solve?

**Proposed Solution**: How should it work?

**openCypher Compatibility**: Does this relate to openCypher spec?
- If yes, provide reference: https://opencypher.org/...

**Examples**:
```cypher
-- Example query
CREATE INDEX ON :Person(name)
```

**Alternatives Considered**: Other approaches you considered

**Additional Context**: Any other relevant information

## Project Structure

```
nxcypher-networkit/
├── src/
│   ├── lib.rs                  # Library entry point
│   ├── python.rs               # PyO3 Python bindings
│   ├── parser/                 # openCypher parser
│   │   ├── mod.rs
│   │   ├── lexer.rs
│   │   └── grammar.rs
│   ├── ast/                    # Abstract syntax tree
│   │   └── builder.rs
│   ├── executor/               # Query executor
│   │   ├── mod.rs
│   │   ├── evaluator.rs
│   │   ├── pattern_matcher.rs
│   │   └── functions/
│   ├── graph/                  # Graph backends
│   │   ├── mod.rs
│   │   ├── backend.rs
│   │   └── backends/
│   │       ├── property_graph.rs
│   │       ├── networkit_rust/
│   │       ├── rustworkx_core/
│   │       └── graphrs/
│   ├── result/                 # Result types
│   │   └── value.rs
│   └── errors.rs               # Error types
├── tests/
│   ├── tck_property_graph.rs   # openCypher TCK tests
│   ├── tck_networkit.rs
│   └── tck/                    # Python TCK (behave)
│       ├── features/
│       ├── steps/
│       └── environment.py
├── python/
│   └── ocg/
│       └── __init__.py         # Python package
├── benches/                    # Benchmarks
│   └── comparison.rs
├── Cargo.toml                  # Rust dependencies
├── pyproject.toml              # Python package config
└── README.md
```

## Release Process

### Version Numbers

Follow [Semantic Versioning](https://semver.org/):
- **MAJOR**: Incompatible API changes (1.0.0 → 2.0.0)
- **MINOR**: New features, backwards-compatible (0.1.0 → 0.2.0)
- **PATCH**: Bug fixes, backwards-compatible (0.1.0 → 0.1.1)

### Creating a Release

1. **Update version** in `Cargo.toml`
2. **Update CHANGELOG.md** with changes
3. **Run full test suite**:
   ```bash
   cargo test --all-features
   cargo test --test tck_property_graph
   ```
4. **Commit changes**:
   ```bash
   git add Cargo.toml CHANGELOG.md
   git commit -m "chore: release v0.2.0"
   git push
   ```
5. **Create and push tag**:
   ```bash
   git tag v0.2.0
   git push origin v0.2.0
   ```
6. **GitHub Actions** will automatically:
   - Build 65+ wheels
   - Run tests on all platforms
   - Publish to PyPI
   - Create GitHub Release

## Communication

### Getting Help

- **Questions**: Open an issue with `question` label
- **Discussions**: Use GitHub Discussions
- **Security**: See [SECURITY.md](SECURITY.md)

### Code of Conduct

This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).

Please be:
- **Respectful** of differing viewpoints
- **Constructive** in feedback
- **Patient** with maintainers and contributors
- **Professional** in all interactions

## License

By contributing, you agree that your contributions will be licensed under the [Apache License 2.0](LICENSE).

All contributions must:
- Be your original work
- Not violate any copyrights or licenses
- Be compatible with Apache 2.0 license

## Recognition

Contributors will be:
- Listed in release notes
- Credited in CHANGELOG.md (for significant contributions)
- Acknowledged in documentation (for major features)

Thank you for contributing to OCG! 🚀
