/**
 * SNMP encoding utilities
 * Contains helper methods for encoding SNMP data
 */
export class SnmpEncoder {
  /**
   * Convert OID string to array of integers
   * @param oid OID string in dotted notation (e.g. "1.3.6.1.2.1")
   * @returns Array of integers representing the OID
   */
  public static oidToArray(oid: string): number[] {
    return oid.split('.').map(n => parseInt(n, 10));
  }

  /**
   * Encode an SNMP integer
   * @param value Integer value to encode
   * @returns Buffer containing the encoded integer
   */
  public static encodeInteger(value: number): Buffer {
    const buf = Buffer.alloc(4);
    buf.writeInt32BE(value, 0);
    
    // Find first non-zero byte
    let start = 0;
    while (start < 3 && buf[start] === 0) {
      start++;
    }
    
    // Handle negative values
    if (value < 0 && buf[start] === 0) {
      start--;
    }
    
    return buf.slice(start);
  }

  /**
   * Encode an OID
   * @param oid Array of integers representing the OID
   * @returns Buffer containing the encoded OID
   */
  public static encodeOID(oid: number[]): Buffer {
    // First two numbers are encoded as 40*x+y
    let encodedOid = Buffer.from([40 * (oid[0] || 0) + (oid[1] || 0)]);
    
    // Encode remaining numbers
    for (let i = 2; i < oid.length; i++) {
      const n = oid[i];
      
      if (n < 128) {
        // Simple case: number fits in one byte
        encodedOid = Buffer.concat([encodedOid, Buffer.from([n])]);
      } else {
        // Number needs multiple bytes
        const bytes = [];
        let value = n;
        
        // Create bytes array in reverse order
        do {
          bytes.unshift(value & 0x7F);
          value >>= 7;
        } while (value > 0);
        
        // Set high bit on all but the last byte
        for (let j = 0; j < bytes.length - 1; j++) {
          bytes[j] |= 0x80;
        }
        
        encodedOid = Buffer.concat([encodedOid, Buffer.from(bytes)]);
      }
    }
    
    return encodedOid;
  }

  /**
   * Decode an ASN.1 integer
   * @param buffer Buffer containing the encoded integer
   * @param offset Offset in the buffer
   * @param length Length of the integer in bytes
   * @returns Decoded integer value
   */
  public static decodeInteger(buffer: Buffer, offset: number, length: number): number {
    if (length === 1) {
      return buffer[offset];
    } else if (length === 2) {
      return buffer.readInt16BE(offset);
    } else if (length === 3) {
      return (buffer[offset] << 16) | (buffer[offset + 1] << 8) | buffer[offset + 2];
    } else if (length === 4) {
      return buffer.readInt32BE(offset);
    } else {
      // For longer integers, we'll just return a simple value
      return buffer[offset];
    }
  }
}