/*
 * IRCNamespace.java
 * IRCCore
 *
 * Created by tarchan on 2006/12/03.
 * Copyright (c) 2006 tarchan. All rights reserved.
 */
package com.mac.tarchan.irc;

import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * IRCNamespace
 * 
 * @author tarchan
 * @author nori090
 */
public class IRCNamespace {
    private ConcurrentHashMap<String, String> keys = new ConcurrentHashMap<String, String>();

    private ConcurrentHashMap<String, Object> namespace = new ConcurrentHashMap<String, Object>();

    /**
     * 指定した key で value を登録します。 ひとつの IRC ネットワークで、ひとつの名前空間を共有します。 チャンネル、ニックネームを含みます。
     * 
     * @param key キー
     * @param value チャンネル、またはニックネーム
     * @return 以前登録していたオブジェクト
     */
    public Object put( String key, Object value ) {
        String upperKey = key.toUpperCase();
        keys.put( upperKey, key );
        return namespace.put( upperKey, value );
    }

    public Object get( String key ) {
        String upperKey = key.toUpperCase();
        return namespace.get( upperKey );
    }

    public Object remove( String key ) {
        String upperKey = key.toUpperCase();
        return namespace.remove( upperKey );
    }

    public String toString() {
        return keys.toString();
    }

    public boolean containsKey( String key ) {
        String upperKey = key.toUpperCase();
        return namespace.containsKey( upperKey );
    }

    public IRCUser userForName( String name ) {
        return containsKey( name ) ? (IRCUser) get( name ) : null;
    }

    public IRCChannel channelForName( String name ) {
        return containsKey( name ) ? (IRCChannel) get( name ) : null;
    }

    /**
     * チャンネル名のパターン チャンネルの名前は50文字以内の文字列です('&'や'#'、'+' 、'!'で始まります)。チャンネルの名前はケースセンシティブではありません(英文字の大文字と小文字は区別されません)。
     * 先頭の文字が'&'か'#'か'+'か'!'(以降"チャンネルプレフィックス"と呼びます)であること以外には、スペース(' ')やコントロールG(^GもしくはASCII
     * 7)、コンマ(','このプロトコルではリストアイテムセパレータとして使われます)を含んでは「いけない」というのがチャンネルネームの唯一の制限です。
     * また、コロン(':')はチャンネルマスクの制限を外すものとして使われます。チャンネルネームの文法の詳細は"IRC Server Protocol" [IRC-SERVER]で定義されています。
     */
    private static final Pattern CHANNEL_PATTERN = Pattern.compile( "^[&#+!%][^\\ \\007,]+" );

    /**
     * ニックネームのパターン チャンネルの衝突しない名前
     */
    private static final Pattern NICK_PATTERN = Pattern.compile( "^@?[^&#+!%]" );

    /**
     * チャンネル名かどうかを判定します。
     * 
     * @param input 入力
     * @return チャンネル名の場合は true、そうでない場合は false
     */
    public static boolean isChannel( String input ) {
        if ( input == null )
            return false;
        return CHANNEL_PATTERN.matcher( input ).matches();
    }

    public static String normalizeChannel( String input, String locale ) {
        // %irodorie -> #irodorie:*.jp
        if ( isChannel( input ) && input.startsWith( "%" ) )
            return "#" + input.substring( 1 ) + ":*." + locale;
        else
            return input;
    }

    public static boolean isNick( String input ) {
        if ( input == null )
            return false;
        return NICK_PATTERN.matcher( input ).find();
    }

    public static String normalizeNick( String input ) {
        // @tarchan -> tarchan
        if ( isNick( input ) && input.startsWith( "@" ) )
            return input.substring( 1 );
        else
            return input;
    }

    private static final Pattern URI_PATTERN =
        Pattern.compile( "(h?ttps?|ftp|rtsp)://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+" );

    private static final Pattern IMG_PATTERN =
        Pattern.compile( "(h?ttps?|ftp|rtsp)://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\.(?i:gif|jpe?g|png|bmp)" );

    public static Matcher uriMatcher( String input ) {
        return URI_PATTERN.matcher( input );
    }

    public static Matcher imageMatcher( String input ) {
        return IMG_PATTERN.matcher( input );
    }

    public static boolean isImage( String input ) {
        if ( input == null )
            return false;
        return IMG_PATTERN.matcher( input ).find();
    }
}
