///////////////////////////////////////////////////////////////////////////////
//
//                          IMPORTANT NOTICE
//
// The following open source license statement does not apply to any
// entity in the Exception List published by FMSoft.
//
// For more information, please visit:
//
// https://www.fmsoft.cn/exception-list
//
//////////////////////////////////////////////////////////////////////////////
/*
 *   This file is part of MiniGUI, a mature cross-platform windowing
 *   and Graphics User Interface (GUI) support system for embedded systems
 *   and smart IoT devices.
 *
 *   Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
 *   Copyright (C) 1998~2002, WEI Yongming
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *   Or,
 *
 *   As this program is a library, any link to this program must follow
 *   GNU General Public License version 3 (GPLv3). If you cannot accept
 *   GPLv3, you need to be licensed from FMSoft.
 *
 *   If you have got a commercial license of this program, please use it
 *   under the terms and conditions of the commercial license.
 *
 *   For more information about the commercial license, please refer to
 *   <http://www.minigui.com/blog/minigui-licensing-policy/>.
 */

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include "common.h"
#include "minigui.h"
#include "gdi.h"

#ifdef _MGCHARSET_UNICODE

#include "unicode-decomp.h"
#include "unicode-comp.h"

#define CC_PART1(Page, Char) \
    ((combining_class_table_part1[Page] >= UCHAR_MAX_TABLE_INDEX) \
     ? (combining_class_table_part1[Page] - UCHAR_MAX_TABLE_INDEX) \
     : (cclass_data[combining_class_table_part1[Page]][Char]))

#define CC_PART2(Page, Char) \
    ((combining_class_table_part2[Page] >= UCHAR_MAX_TABLE_INDEX) \
     ? (combining_class_table_part2[Page] - UCHAR_MAX_TABLE_INDEX) \
     : (cclass_data[combining_class_table_part2[Page]][Char]))

#define COMBINING_CLASS(Char) \
    (((Char) <= UCHAR_LAST_CHAR_PART1) \
     ? CC_PART1 ((Char) >> 8, (Char) & 0xff) \
     : (((Char) >= 0xe0000 && (Char) <= UCHAR_LAST_CHAR) \
         ? CC_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
         : 0))

int UCharCombiningClass (Uchar32 uc)
{
    return COMBINING_CLASS (uc);
}

/* constants for hangul syllable [de]composition */
#define SBase 0xAC00
#define LBase 0x1100
#define VBase 0x1161
#define TBase 0x11A7
#define LCount 19
#define VCount 21
#define TCount 28
#define NCount (VCount * TCount)
#define SCount (LCount * NCount)

void UCharCanonicalOrdering (Uchar32 *string, int len)
{
    int i;
    int swap = 1;

    while (swap)
    {
        int last;
        swap = 0;
        last = COMBINING_CLASS (string[0]);
        for (i = 0; i < len - 1; ++i)
        {
            int next = COMBINING_CLASS (string[i + 1]);
            if (next != 0 && last > next)
            {
                int j;
                /* Percolate item leftward through string.  */
                for (j = i + 1; j > 0; --j)
                {
                    Uchar32 t;
                    if (COMBINING_CLASS (string[j - 1]) <= next)
                        break;
                    t = string[j];
                    string[j] = string[j - 1];
                    string[j - 1] = t;
                    swap = 1;
                }
                /* We're re-entering the loop looking at the old
                   character again.  */
                next = last;
            }
            last = next;
        }
    }
}

/* http://www.unicode.org/unicode/reports/tr15/#Hangul
 * r should be null or have sufficient space. Calling with r == NULL will
 * only calculate the result_len; however, a buffer with space for three
 * characters will always be big enough. */
static void decompose_hangul (Uchar32 s, Uchar32 *r, int *result_len)
{
    int SIndex = s - SBase;
    int TIndex = SIndex % TCount;

    if (r)
    {
        r[0] = LBase + SIndex / NCount;
        r[1] = VBase + (SIndex % NCount) / TCount;
    }

    if (TIndex)
    {
        if (r)
            r[2] = TBase + TIndex;
        *result_len = 3;
    }
    else
        *result_len = 2;
}

/* returns a pointer to a null-terminated UTF-8 string */
static const unsigned char * find_decomposition (Uchar32 ch, BOOL compat)
{
    int start = 0;
    int end = TABLESIZE (decomp_table);

    if (ch >= decomp_table[start].ch &&
            ch <= decomp_table[end - 1].ch) {
        while (TRUE) {
            int half = (start + end) / 2;
            if (ch == decomp_table[half].ch) {
                int offset;

                if (compat) {
                    offset = decomp_table[half].compat_offset;
                    if (offset == UCHAR_NOT_PRESENT_OFFSET)
                        offset = decomp_table[half].canon_offset;
                }
                else {
                    offset = decomp_table[half].canon_offset;
                    if (offset == UCHAR_NOT_PRESENT_OFFSET)
                        return NULL;
                }

                return &(decomp_expansion_string[offset]);
            }
            else if (half == start)
                break;
            else if (ch > decomp_table[half].ch)
                start = half;
            else
                end = half;
        }
    }

    return NULL;
}

/* L,V => LV and LV,T => LVT  */
static BOOL combine_hangul (Uchar32 a, Uchar32 b, Uchar32 *result)
{
    int LIndex = a - LBase;
    int SIndex = a - SBase;

    int VIndex = b - VBase;
    int TIndex = b - TBase;

    if (0 <= LIndex && LIndex < LCount
            && 0 <= VIndex && VIndex < VCount) {
        *result = SBase + (LIndex * VCount + VIndex) * TCount;
        return TRUE;
    }
    else if (0 <= SIndex && SIndex < SCount && (SIndex % TCount) == 0
            && 0 < TIndex && TIndex < TCount) {
        *result = a + TIndex;
        return TRUE;
    }

    return FALSE;
}

#define CI(Page, Char) \
    ((compose_table[Page] >= UCHAR_MAX_TABLE_INDEX) \
     ? (compose_table[Page] - UCHAR_MAX_TABLE_INDEX) \
     : (compose_data[compose_table[Page]][Char]))

#define COMPOSE_INDEX(Char) \
    (((Char >> 8) > (COMPOSE_TABLE_LAST)) ? 0 : CI((Char) >> 8, (Char) & 0xff))

static BOOL combine (Uchar32  a, Uchar32  b, Uchar32 *result)
{
    unsigned short index_a, index_b;

    if (combine_hangul (a, b, result))
        return TRUE;

    index_a = COMPOSE_INDEX(a);

    if (index_a >= COMPOSE_FIRST_SINGLE_START && index_a < COMPOSE_SECOND_START)
    {
        if (b == compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][0])
        {
            *result = compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][1];
            return TRUE;
        }
        else
            return FALSE;
    }

    index_b = COMPOSE_INDEX(b);

    if (index_b >= COMPOSE_SECOND_SINGLE_START)
    {
        if (a == compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][0])
        {
            *result = compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][1];
            return TRUE;
        }
        else
            return FALSE;
    }

    if (index_a >= COMPOSE_FIRST_START && index_a < COMPOSE_FIRST_SINGLE_START &&
            index_b >= COMPOSE_SECOND_START && index_b < COMPOSE_SECOND_SINGLE_START)
    {
        Uchar32 res = compose_array[index_a - COMPOSE_FIRST_START][index_b - COMPOSE_SECOND_START];

        if (res)
        {
            *result = res;
            return TRUE;
        }
    }

    return FALSE;
}

static BOOL decompose_hangul_step (Uchar32  ch, Uchar32 *a, Uchar32 *b)
{
    int SIndex, TIndex;

    if (ch < SBase || ch >= SBase + SCount)
        return FALSE;  /* not a hangul syllable */

    SIndex = ch - SBase;
    TIndex = SIndex % TCount;

    if (TIndex) {
        /* split LVT -> LV,T */
        *a = ch - TIndex;
        *b = TBase + TIndex;
    }
    else {
        /* split LV -> L,V */
        *a = LBase + SIndex / NCount;
        *b = VBase + (SIndex % NCount) / TCount;
    }

    return TRUE;
}

BOOL UCharDecompose (Uchar32 ch, Uchar32 *a, Uchar32 *b)
{
    int start = 0;
    int end = TABLESIZE (decomp_step_table);

    if (decompose_hangul_step (ch, a, b))
        return TRUE;

    /* TODO use bsearch() */
    if (ch >= decomp_step_table[start].ch &&
            ch <= decomp_step_table[end - 1].ch)
    {
        while (TRUE)
        {
            int half = (start + end) / 2;
            const decomposition_step *p = &(decomp_step_table[half]);
            if (ch == p->ch)
            {
                *a = p->a;
                *b = p->b;
                return TRUE;
            }
            else if (half == start)
                break;
            else if (ch > p->ch)
                start = half;
            else
                end = half;
        }
    }

    *a = ch;
    *b = 0;

    return FALSE;
}

BOOL UCharCompose (Uchar32 a, Uchar32 b, Uchar32 *ch)
{
    if (combine (a, b, ch))
        return TRUE;

    *ch = 0;
    return FALSE;
}

#define UTF8_COMPUTE(Char, Mask, Len)       \
if (Char < 128)                             \
{                                           \
    Len = 1;                                \
    Mask = 0x7f;                            \
}                                           \
else if ((Char & 0xe0) == 0xc0)             \
{                                           \
    Len = 2;                                \
    Mask = 0x1f;                            \
}                                           \
else if ((Char & 0xf0) == 0xe0)             \
{                                           \
    Len = 3;                                \
    Mask = 0x0f;                            \
}                                           \
else if ((Char & 0xf8) == 0xf0)             \
{                                           \
    Len = 4;                                \
    Mask = 0x07;                            \
}                                           \
else if ((Char & 0xfc) == 0xf8)             \
{                                           \
    Len = 5;                                \
    Mask = 0x03;                            \
}                                           \
else if ((Char & 0xfe) == 0xfc)             \
{                                           \
    Len = 6;                                \
    Mask = 0x01;                            \
}                                           \
else                                        \
Len = -1;

#define UTF8_LENGTH(Char)                   \
    ((Char) < 0x80 ? 1 :                    \
     ((Char) < 0x800 ? 2 :                  \
      ((Char) < 0x10000 ? 3 :               \
       ((Char) < 0x200000 ? 4 :             \
        ((Char) < 0x4000000 ? 5 : 6)))))

#define UTF8_GET(Result, Chars, Count, Mask, Len)       \
    (Result) = (Chars)[0] & (Mask);                     \
for ((Count) = 1; (Count) < (Len); ++(Count))           \
{                                                       \
    if (((Chars)[(Count)] & 0xc0) != 0x80)              \
    {                                                   \
        (Result) = -1;                                  \
        break;                                          \
    }                                                   \
    (Result) <<= 6;                                     \
    (Result) |= ((Chars)[(Count)] & 0x3f);              \
}

static Uchar32 utf8_to_uchar32 (const unsigned char *p)
{
    int i, mask = 0, len;
    Uchar32 result;
    unsigned char c = (unsigned char) *p;

    UTF8_COMPUTE (c, mask, len);
    if (len == -1)
        return (Uchar32)-1;
    UTF8_GET (result, p, i, mask, len);

    return result;
}

#define UNICODE_VALID(Char)                   \
    ((Char) < 0x110000 &&                     \
     (((Char) & 0xFFFFF800) != 0xD800))

static const unsigned char utf8_skip_data[256] = {
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
};

#define utf8_next_char(p) ((p) + utf8_skip_data[*(p)])

static int utf8_strlen (const unsigned char *p, int max)
{
    int len = 0;
    const unsigned char *start = p;
    if (p == NULL && max == 0)
        return 0;

    if (max < 0) {
        while (*p) {
            p = utf8_next_char (p);
            ++len;
        }
    }
    else {
        if (max == 0 || !*p)
            return 0;

        p = utf8_next_char (p);

        while (p - start < max && *p) {
            ++len;
            p = utf8_next_char (p);
        }

        /* only do the last len increment if we got a complete
         * char (don't count partial chars)
         */
        if (p - start <= max)
            ++len;
    }

    return len;
}

int UCharFullyDecompose (Uchar32  ch, BOOL compat, Uchar32 *result, int result_len)
{
    const unsigned char *decomp;
    const unsigned char *p;

    /* Hangul syllable */
    if (ch >= SBase && ch < SBase + SCount) {
        int len, i;
        Uchar32 buffer[3];
        decompose_hangul (ch, result ? buffer : NULL, &len);
        if (result)
            for (i = 0; i < len && i < result_len; i++)
                result[i] = buffer[i];
        return len;
    }
    else if ((decomp = find_decomposition (ch, compat)) != NULL)
    {
        /* Found it.  */
        int len, i;

        len = utf8_strlen (decomp, -1);

        for (p = decomp, i = 0; i < len && i < result_len; p = utf8_next_char (p), i++)
            result[i] = utf8_to_uchar32 (p);

        return len;
    }

    /* Does not decompose */
    if (result && result_len >= 1)
        *result = ch;
    return 1;
}

#endif /* _MGCHARSET_UNICODE */


{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
module Nix.String
  ( NixString
  , principledGetContext
  , principledMakeNixString
  , principledMempty
  , StringContext(..)
  , ContextFlavor(..)
  , NixLikeContext(..)
  , NixLikeContextValue(..)
  , toNixLikeContext
  , fromNixLikeContext
  , stringHasContext
  , principledIntercalateNixString
  , hackyGetStringNoContext
  , principledGetStringNoContext
  , principledStringIgnoreContext
  , hackyStringIgnoreContext
  , hackyMakeNixStringWithoutContext
  , principledMakeNixStringWithoutContext
  , principledMakeNixStringWithSingletonContext
  , principledModifyNixContents
  , principledStringMappend
  , principledStringMempty
  , principledStringMConcat
  , WithStringContext
  , WithStringContextT(..)
  , extractNixString
  , addStringContext
  , addSingletonStringContext
  , runWithStringContextT
  , runWithStringContext
  )
where

import           Control.Monad.Writer
import           Data.Functor.Identity
import qualified Data.HashMap.Lazy             as M
import qualified Data.HashSet                  as S
import           Data.Hashable
import           Data.Text                      ( Text )
import qualified Data.Text                     as Text
import           GHC.Generics

-- {-# WARNING hackyGetStringNoContext, hackyStringIgnoreContext, hackyMakeNixStringWithoutContext "This NixString function needs to be replaced" #-}

-- | A 'ContextFlavor' describes the sum of possible derivations for string contexts
data ContextFlavor =
    DirectPath
  | AllOutputs
  | DerivationOutput !Text
  deriving (Show, Eq, Ord, Generic)

instance Hashable ContextFlavor

-- | A 'StringContext' ...
data StringContext =
  StringContext { scPath :: !Text
                , scFlavor :: !ContextFlavor
                } deriving (Eq, Ord, Show, Generic)

instance Hashable StringContext

data NixString = NixString
  { nsContents :: !Text
  , nsContext :: !(S.HashSet StringContext)
  } deriving (Eq, Ord, Show, Generic)

instance Hashable NixString

newtype NixLikeContext = NixLikeContext
  { getNixLikeContext :: M.HashMap Text NixLikeContextValue
  } deriving (Eq, Ord, Show, Generic)

data NixLikeContextValue = NixLikeContextValue
  { nlcvPath :: !Bool
  , nlcvAllOutputs :: !Bool
  , nlcvOutputs :: ![Text]
  } deriving (Show, Eq, Ord, Generic)

instance Semigroup NixLikeContextValue where
  a <> b = NixLikeContextValue
    { nlcvPath       = nlcvPath a || nlcvPath b
    , nlcvAllOutputs = nlcvAllOutputs a || nlcvAllOutputs b
    , nlcvOutputs    = nlcvOutputs a <> nlcvOutputs b
    }

instance Monoid NixLikeContextValue where
  mempty = NixLikeContextValue False False []

toStringContexts :: (Text, NixLikeContextValue) -> [StringContext]
toStringContexts (path, nlcv) = case nlcv of
  NixLikeContextValue True _ _ -> StringContext path DirectPath
    : toStringContexts (path, nlcv { nlcvPath = False })
  NixLikeContextValue _ True _ -> StringContext path AllOutputs
    : toStringContexts (path, nlcv { nlcvAllOutputs = False })
  NixLikeContextValue _ _ ls | not (null ls) ->
    map (StringContext path . DerivationOutput) ls
  _ -> []

toNixLikeContextValue :: StringContext -> (Text, NixLikeContextValue)
toNixLikeContextValue sc = (,) (scPath sc) $ case scFlavor sc of
  DirectPath         -> NixLikeContextValue True False []
  AllOutputs         -> NixLikeContextValue False True []
  DerivationOutput t -> NixLikeContextValue False False [t]

toNixLikeContext :: S.HashSet StringContext -> NixLikeContext
toNixLikeContext stringContext = NixLikeContext
  $ S.foldr go mempty stringContext
 where
  go sc hm =
    let (t, nlcv) = toNixLikeContextValue sc in M.insertWith (<>) t nlcv hm

fromNixLikeContext :: NixLikeContext -> S.HashSet StringContext
fromNixLikeContext =
  S.fromList . join . map toStringContexts . M.toList . getNixLikeContext

principledGetContext :: NixString -> S.HashSet StringContext
principledGetContext = nsContext

-- | Combine two NixStrings using mappend
principledMempty :: NixString
principledMempty = NixString "" mempty

-- | Combine two NixStrings using mappend
principledStringMappend :: NixString -> NixString -> NixString
principledStringMappend (NixString s1 t1) (NixString s2 t2) =
  NixString (s1 <> s2) (t1 <> t2)

-- | Combine two NixStrings using mappend
hackyStringMappend :: NixString -> NixString -> NixString
hackyStringMappend (NixString s1 t1) (NixString s2 t2) =
  NixString (s1 <> s2) (t1 <> t2)

-- | Combine NixStrings with a separator
principledIntercalateNixString :: NixString -> [NixString] -> NixString
principledIntercalateNixString _   []   = principledMempty
principledIntercalateNixString _   [ns] = ns
principledIntercalateNixString sep nss  = NixString contents ctx
 where
  contents = Text.intercalate (nsContents sep) (map nsContents nss)
  ctx      = S.unions (nsContext sep : map nsContext nss)

-- | Combine NixStrings using mconcat
hackyStringMConcat :: [NixString] -> NixString
hackyStringMConcat = foldr hackyStringMappend (NixString mempty mempty)

-- | Empty string with empty context.
principledStringMempty :: NixString
principledStringMempty = NixString mempty mempty

-- | Combine NixStrings using mconcat
principledStringMConcat :: [NixString] -> NixString
principledStringMConcat =
  foldr principledStringMappend (NixString mempty mempty)

--instance Semigroup NixString where
  --NixString s1 t1 <> NixString s2 t2 = NixString (s1 <> s2) (t1 <> t2)

--instance Monoid NixString where
--  mempty = NixString mempty mempty
--  mappend = (<>)

-- | Extract the string contents from a NixString that has no context
hackyGetStringNoContext :: NixString -> Maybe Text
hackyGetStringNoContext (NixString s c) | null c    = Just s
                                        | otherwise = Nothing

-- | Extract the string contents from a NixString that has no context
principledGetStringNoContext :: NixString -> Maybe Text
principledGetStringNoContext (NixString s c) | null c    = Just s
                                             | otherwise = Nothing

-- | Extract the string contents from a NixString even if the NixString has an associated context
principledStringIgnoreContext :: NixString -> Text
principledStringIgnoreContext (NixString s _) = s

-- | Extract the string contents from a NixString even if the NixString has an associated context
hackyStringIgnoreContext :: NixString -> Text
hackyStringIgnoreContext (NixString s _) = s

-- | Returns True if the NixString has an associated context
stringHasContext :: NixString -> Bool
stringHasContext (NixString _ c) = not (null c)

-- | Constructs a NixString without a context
hackyMakeNixStringWithoutContext :: Text -> NixString
hackyMakeNixStringWithoutContext = flip NixString mempty

-- | Constructs a NixString without a context
principledMakeNixStringWithoutContext :: Text -> NixString
principledMakeNixStringWithoutContext = flip NixString mempty

-- | Modify the string part of the NixString, leaving the context unchanged
principledModifyNixContents :: (Text -> Text) -> NixString -> NixString
principledModifyNixContents f (NixString s c) = NixString (f s) c

-- | Create a NixString using a singleton context
principledMakeNixStringWithSingletonContext
  :: Text -> StringContext -> NixString
principledMakeNixStringWithSingletonContext s c = NixString s (S.singleton c)

-- | Create a NixString from a Text and context
principledMakeNixString :: Text -> S.HashSet StringContext -> NixString
principledMakeNixString s c = NixString s c

-- | A monad for accumulating string context while producing a result string.
newtype WithStringContextT m a = WithStringContextT (WriterT (S.HashSet StringContext) m a)
  deriving (Functor, Applicative, Monad, MonadTrans, MonadWriter (S.HashSet StringContext))

type WithStringContext = WithStringContextT Identity

-- | Add 'StringContext's into the resulting set.
addStringContext
  :: Monad m => S.HashSet StringContext -> WithStringContextT m ()
addStringContext = WithStringContextT . tell

-- | Add a 'StringContext' into the resulting set.
addSingletonStringContext :: Monad m => StringContext -> WithStringContextT m ()
addSingletonStringContext = WithStringContextT . tell . S.singleton

-- | Get the contents of a 'NixString' and write its context into the resulting set.
extractNixString :: Monad m => NixString -> WithStringContextT m Text
extractNixString (NixString s c) = WithStringContextT $ tell c >> pure s

-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContextT :: Monad m => WithStringContextT m Text -> m NixString
runWithStringContextT (WithStringContextT m) =
  uncurry NixString <$> runWriterT m

-- | Run an action producing a string with a context and put those into a 'NixString'.
runWithStringContext :: WithStringContextT Identity Text -> NixString
runWithStringContext = runIdentity . runWithStringContextT


package br.com.edsilfer.emojilibrary.controller

import android.os.Build
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.view.View
import android.widget.LinearLayout
import androidx.appcompat.widget.Toolbar
import br.com.edsilfer.emojilibrary.R
import br.com.edsilfer.emojilibrary.view.EmojiActivity
import br.com.edsilfer.emojilibrary.view.EmojiActivity.OnBackPressedListener
import br.com.edsilfer.emojilibrary.view.EmojiEditText
import br.com.edsilfer.emojilibrary.view.EmojiKeyboard
import br.com.edsilfer.emojilibrary.view.listeners.KeyboardListener
import br.com.edsilfer.emojilibrary.view.listeners.PanelEventListener

class PanelController(
        private val context: EmojiActivity,
        private val listener: PanelEventListener?
) : KeyboardListener, TextWatcher {

    private var toogleIcon = true
    private val emojiKeyboard: EmojiKeyboard
    private var isEmojiKeyboardVisible = false

    private var panel: Toolbar = context.findViewById<View>(R.id.panel) as Toolbar
    private var input: EmojiEditText = panel.findViewById<View>(R.id.input) as EmojiEditText
    private var curtain: LinearLayout = context.findViewById<View>(R.id.curtain) as LinearLayout

    var text: String
        get() = input.text.toString()
        set(text) {
            input.setText(text)
        }

    init {
        initBottomPanel()
        setInputConfig()
        onBackPressed()
        emojiKeyboard = EmojiKeyboard(context, input)
    }

    private fun initBottomPanel() {
        panel.setNavigationIcon(R.drawable.input_emoji)
        panel.setTitleTextColor(-0x1)
        panel.inflateMenu(R.menu.telegram_menu)
        panel.setNavigationOnClickListener {
            if (isEmojiKeyboardVisible) {
                curtain.visibility = LinearLayout.INVISIBLE
                if (input.isKeyboardVisible) {
                    panel.setNavigationIcon(R.drawable.ic_keyboard_grey600_24dp)
                    input.hideSoftKeyboard()
                } else {
                    panel.setNavigationIcon(R.drawable.input_emoji)
                    input.showSoftKeyboard()
                }
            } else {
                panel.setNavigationIcon(R.drawable.ic_keyboard_grey600_24dp)
                curtain.visibility = LinearLayout.INVISIBLE
                showEmojiKeyboard()
            }

        }
        panel.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.action_attach -> listener?.onAttachClicked()
                R.id.action_mic -> if (text.isEmpty()) listener?.onMicClicked() else listener?.onSendClicked()
            }
            false
        }
    }

    private fun setInputConfig() {
        input.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
        input.addKeyboardListener(this)
        input.addTextChangedListener(this)
    }

    override fun keyboardVisible() {
        curtain.visibility = LinearLayout.VISIBLE
        showEmojiKeyboard()
    }

    override fun keyboardHidden() {
        curtain.visibility = LinearLayout.INVISIBLE
        hideEmojiKeyboard()
    }

    /*
    Handles the animation of the panel buttons when text is written in the EditText
     */
    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        val micButton = panel.menu.findItem(R.id.action_mic)
        if (text.isNotEmpty() && toogleIcon) {
            toogleIcon = false
            panel.findViewById<View>(R.id.action_attach).animate().scaleX(0f).scaleY(0f).setDuration(150).start()
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                panel.findViewById<View>(R.id.action_mic).animate().scaleX(0f).scaleY(0f).setDuration(75).withEndAction {
                    micButton.setIcon(R.drawable.ic_send_telegram)
                    panel.findViewById<View>(R.id.action_mic).animate().scaleX(1f).scaleY(1f).setDuration(75).start()
                }.start()
            }
        } else if (text.isEmpty()) {
            toogleIcon = true
            panel.findViewById<View>(R.id.action_attach).animate().scaleX(1f).scaleY(1f).setDuration(150).start()
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                panel.findViewById<View>(R.id.action_mic).animate().scaleX(0f).scaleY(0f).setDuration(75).withEndAction {
                    micButton.setIcon(R.drawable.ic_microphone_grey600_24dp)
                    panel.findViewById<View>(R.id.action_mic).animate().scaleX(1f).scaleY(1f).setDuration(75).start()
                }.start()
            }
        }
    }

    private fun onBackPressed() {
        context.setOnBackPressed(object : OnBackPressedListener {
            override fun onBackPressed(): Boolean? {
                if (isEmojiKeyboardVisible) {
                    hideEmojiKeyboard()
                    return true
                }
                return false
            }
        })
    }

    private fun showEmojiKeyboard() {
        isEmojiKeyboardVisible = true
        emojiKeyboard.keyboardLayout.visibility = LinearLayout.VISIBLE
        curtain.visibility = LinearLayout.INVISIBLE
    }

    private fun hideEmojiKeyboard() {
        isEmojiKeyboardVisible = false
        panel.setNavigationIcon(R.drawable.input_emoji)
        emojiKeyboard.keyboardLayout.visibility = LinearLayout.GONE
        curtain.visibility = LinearLayout.VISIBLE
    }

    /*
    DO NOTHING
     */
    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}

    override fun afterTextChanged(p0: Editable?) {}
}


.page-reward {
    margin: 60px 0;
    text-align: center;
}
.page-reward-btn {
    width: 56px;
    height: 56px;
    line-height: 56px;
    font-size: 20px;
    color: #fff;
    background: #f44336;
    .boxShadow();
    &:hover,
    &:active {
        color: #fff;
        text-decoration: none;
    }
}

.reward-title {
    position: relative;
    padding: 10px 30px;

    .icon-quote-left,
    .icon-quote-right {
        position: absolute;
        font-size: 80%;
        color: #999;
    }
    .icon-quote-left {
        top: 0;
        left: 0;
    }
    .icon-quote-right {
        bottom: 0;
        right: 0;
    }
}
.reward-lay {
    max-width: 100%;
    width: 360px;
}
.reward-content {
    margin: 20px 0;
}
.reward-code {
    width: 200px;
    margin: 0 auto;
}

.reward-toggle {
    position: relative;
    display: block;
    width: 120px;
    overflow: hidden;
    margin: 40px auto 0;
    border-radius: 3px;
    cursor: pointer;
    .boxShadow();

    &-check {
        position: absolute;
        visibility: hidden;
        &:checked {
            +.reward-toggle-ctrol {
                .transform(translate3d(-60px, 0, 0))
            }
        }
    }

    &-ctrol {
        display: flex;
        width: 180px;
        height: 30px;
        line-height: 30px;
        background: #eee;
        border-radius: 3px;
        overflow: hidden;
        user-select: none;
        .transition(.1s)
    }

    &-item,
    &-label {
        flex: 0 0 auto;
        width: 60px;
        height: 100%;
    }

    &-item {
        position: relative;
        z-index: 2;
        height: 100%;
        text-align: center;
        color: #fff;
        font-size: 12px;
        box-shadow: inset 0 0 15px rgba(0, 0, 0, .3)
    }
    .alipay {
        background: #1e88e5;
    }
    .wechat {
        background: #4caf50;
    }
}

@media screen and (max-width:760px) {
    .reward-title {
        font-size: 18px;
    }
}

@media screen and (max-width: 480px) {
    .reward-lay {
        border-radius: 0
    }
    .reward-content {
        margin: 0;
    }
    .reward-toggle {
        margin: 20px auto 0
    }
}


// SPDX-License-Identifier: GPL-2.0
//
// LED Kernel Transient Trigger
//
// Transient trigger allows one shot timer activation. Please refer to
// Documentation/leds/ledtrig-transient.txt for details
// Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
//
// Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
// ledtrig-heartbeat.c
// Design and use-case input from Jonas Bonn <jonas@southpole.se> and
// Neil Brown <neilb@suse.de>

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/leds.h>
#include "../leds.h"

struct transient_trig_data {
	int activate;
	int state;
	int restore_state;
	unsigned long duration;
	struct timer_list timer;
	struct led_classdev *led_cdev;
};

static void transient_timer_function(struct timer_list *t)
{
	struct transient_trig_data *transient_data =
		from_timer(transient_data, t, timer);
	struct led_classdev *led_cdev = transient_data->led_cdev;

	transient_data->activate = 0;
	led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
}

static ssize_t transient_activate_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct transient_trig_data *transient_data =
		led_trigger_get_drvdata(dev);

	return sprintf(buf, "%d\n", transient_data->activate);
}

static ssize_t transient_activate_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	struct led_classdev *led_cdev = led_trigger_get_led(dev);
	struct transient_trig_data *transient_data =
		led_trigger_get_drvdata(dev);
	unsigned long state;
	ssize_t ret;

	ret = kstrtoul(buf, 10, &state);
	if (ret)
		return ret;

	if (state != 1 && state != 0)
		return -EINVAL;

	/* cancel the running timer */
	if (state == 0 && transient_data->activate == 1) {
		del_timer(&transient_data->timer);
		transient_data->activate = state;
		led_set_brightness_nosleep(led_cdev,
					transient_data->restore_state);
		return size;
	}

	/* start timer if there is no active timer */
	if (state == 1 && transient_data->activate == 0 &&
	    transient_data->duration != 0) {
		transient_data->activate = state;
		led_set_brightness_nosleep(led_cdev, transient_data->state);
		transient_data->restore_state =
		    (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
		mod_timer(&transient_data->timer,
			  jiffies + msecs_to_jiffies(transient_data->duration));
	}

	/* state == 0 && transient_data->activate == 0
		timer is not active - just return */
	/* state == 1 && transient_data->activate == 1
		timer is already active - just return */

	return size;
}

static ssize_t transient_duration_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct transient_trig_data *transient_data = led_trigger_get_drvdata(dev);

	return sprintf(buf, "%lu\n", transient_data->duration);
}

static ssize_t transient_duration_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	struct transient_trig_data *transient_data =
		led_trigger_get_drvdata(dev);
	unsigned long state;
	ssize_t ret;

	ret = kstrtoul(buf, 10, &state);
	if (ret)
		return ret;

	transient_data->duration = state;
	return size;
}

static ssize_t transient_state_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct transient_trig_data *transient_data =
		led_trigger_get_drvdata(dev);
	int state;

	state = (transient_data->state == LED_FULL) ? 1 : 0;
	return sprintf(buf, "%d\n", state);
}

static ssize_t transient_state_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t size)
{
	struct transient_trig_data *transient_data =
		led_trigger_get_drvdata(dev);
	unsigned long state;
	ssize_t ret;

	ret = kstrtoul(buf, 10, &state);
	if (ret)
		return ret;

	if (state != 1 && state != 0)
		return -EINVAL;

	transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
	return size;
}

static DEVICE_ATTR(activate, 0644, transient_activate_show,
		   transient_activate_store);
static DEVICE_ATTR(duration, 0644, transient_duration_show,
		   transient_duration_store);
static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);

static struct attribute *transient_trig_attrs[] = {
	&dev_attr_activate.attr,
	&dev_attr_duration.attr,
	&dev_attr_state.attr,
	NULL
};
ATTRIBUTE_GROUPS(transient_trig);

static int transient_trig_activate(struct led_classdev *led_cdev)
{
	struct transient_trig_data *tdata;

	tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
	if (!tdata)
		return -ENOMEM;

	led_set_trigger_data(led_cdev, tdata);
	tdata->led_cdev = led_cdev;

	timer_setup(&tdata->timer, transient_timer_function, 0);

	return 0;
}

static void transient_trig_deactivate(struct led_classdev *led_cdev)
{
	struct transient_trig_data *transient_data = led_get_trigger_data(led_cdev);

	del_timer_sync(&transient_data->timer);
	led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
	kfree(transient_data);
}

static struct led_trigger transient_trigger = {
	.name     = "transient",
	.activate = transient_trig_activate,
	.deactivate = transient_trig_deactivate,
	.groups = transient_trig_groups,
};
module_led_trigger(transient_trigger);

MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
MODULE_DESCRIPTION("Transient LED trigger");
MODULE_LICENSE("GPL v2");


/*-
 * Copyright 2012-2015 Matthew Endsley
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef TINYSTL_BUFFER_H
#define TINYSTL_BUFFER_H

#include "allocator.h"
#include "new.h"
#include "traits.h"

namespace tinystl {
    template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
    struct buffer {
        T* first;
        T* last;
        T* capacity;
    };

    template<typename T>
    static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits<T, false>) {
        for (; first < last; ++first)
            first->~T();
    }

    template<typename T>
    static inline void buffer_destroy_range_traits(T*, T*, pod_traits<T, true>) {
    }

    template<typename T>
    static inline void buffer_destroy_range(T* first, T* last) {
        buffer_destroy_range_traits(first, last, pod_traits<T>());
    }

    template<typename T>
    static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, false>) {
        for (; first < last; ++first)
            new(placeholder(), first) T();
    }

    template<typename T>
    static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, true>) {
        for (; first < last; ++first)
            *first = T();
    }

    template<typename T>
    static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, false>) {
        for (; first < last; ++first)
            new(placeholder(), first) T(value);
    }

    template<typename T>
    static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, true>) {
        for (; first < last; ++first)
            *first = value;
    }

    template<typename T>
    static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
        for (T* it = first; it != last; ++it, ++dest)
            move_construct(dest, *it);
        buffer_destroy_range(first, last);
    }

    template<typename T>
    static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
        for (; first != last; ++first, ++dest)
            *dest = *first;
    }

    template<typename T>
    static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
        dest += (last - first);
        for (T* it = last; it != first; --it, --dest) {
            move_construct(dest - 1, *(it - 1));
            buffer_destroy_range(it - 1, it);
        }
    }

    template<typename T>
    static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
        dest += (last - first);
        for (T* it = last; it != first; --it, --dest)
            *(dest - 1) = *(it - 1);
    }

    template<typename T>
    static inline void buffer_move_urange(T* dest, T* first, T* last) {
        buffer_move_urange_traits(dest, first, last, pod_traits<T>());
    }

    template<typename T>
    static inline void buffer_bmove_urange(T* dest, T* first, T* last) {
        buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
    }

    template<typename T>
    static inline void buffer_fill_urange(T* first, T* last) {
        buffer_fill_urange_traits(first, last, pod_traits<T>());
    }

    template<typename T>
    static inline void buffer_fill_urange(T* first, T* last, const T& value) {
        buffer_fill_urange_traits(first, last, value, pod_traits<T>());
    }

    template<typename T, typename Alloc>
    static inline void buffer_init(buffer<T, Alloc>* b) {
        b->first = b->last = b->capacity = 0;
    }

    template<typename T, typename Alloc>
    static inline void buffer_destroy(buffer<T, Alloc>* b) {
        buffer_destroy_range(b->first, b->last);
        Alloc::static_deallocate(b->first, (size_t)((char*)b->capacity - (char*)b->first));
    }

    template<typename T, typename Alloc>
    static inline void buffer_reserve(buffer<T, Alloc>* b, size_t capacity) {
        if (b->first + capacity <= b->capacity)
            return;

        typedef T* pointer;
        const size_t size = (size_t)(b->last - b->first);
        pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity);
        buffer_move_urange(newfirst, b->first, b->last);
        Alloc::static_deallocate(b->first, sizeof(T) * capacity);

        b->first = newfirst;
        b->last = newfirst + size;
        b->capacity = newfirst + capacity;
    }

    template<typename T, typename Alloc>
    static inline void buffer_resize(buffer<T, Alloc>* b, size_t size) {
        buffer_reserve(b, size);

        buffer_fill_urange(b->last, b->first + size);
        buffer_destroy_range(b->first + size, b->last);
        b->last = b->first + size;
    }

    template<typename T, typename Alloc>
    static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
        buffer_reserve(b, size);

        buffer_fill_urange(b->last, b->first + size, value);
        buffer_destroy_range(b->first + size, b->last);
        b->last = b->first + size;
    }

    template<typename T, typename Alloc>
    static inline void buffer_shrink_to_fit(buffer<T, Alloc>* b) {
        if (b->last == b->first) {
            const size_t capacity = (size_t)(b->last - b->first);
            Alloc::static_deallocate(b->first, sizeof(T)*capacity);
            b->capacity = b->first;
        }
        else if (b->capacity != b->last) {
            const size_t capacity = (size_t)(b->capacity - b->first);
            const size_t size = (size_t)(b->last - b->first);
            T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size);
            buffer_move_urange(newfirst, b->first, b->last);
            Alloc::static_deallocate(b->first, sizeof(T) * capacity);
            b->first = newfirst;
            b->last = newfirst + size;
            b->capacity = b->last;
        }
    }

    template<typename T, typename Alloc>
    static inline void buffer_clear(buffer<T, Alloc>* b) {
        buffer_destroy_range(b->first, b->last);
        b->last = b->first;
    }

    template<typename T, typename Alloc>
    static inline T* buffer_insert_common(buffer<T, Alloc>* b, T* where, size_t count) {
        const size_t offset = (size_t)(where - b->first);
        const size_t newsize = (size_t)((b->last - b->first) + count);
        if (b->first + newsize > b->capacity)
            buffer_reserve(b, (newsize * 3) / 2);

        where = b->first + offset;

        if (where != b->last)
            buffer_bmove_urange(where + count, where, b->last);

        b->last = b->first + newsize;

        return where;
    }

    template<typename T, typename Alloc, typename Param>
    static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const Param* first, const Param* last) {
        typedef const char* pointer;
        const size_t count = last - first;
        const bool frombuf = ((pointer)b->first <= (pointer)first && (pointer)b->last >= (pointer)last);
        size_t offset = 0;
        if (frombuf) {
            offset = (pointer)first - (pointer)b->first;
            if ((pointer)where <= (pointer)first)
                offset += count * sizeof(T);
        }
        where = buffer_insert_common(b, where, count);
        if (frombuf) {
            first = (Param*)((pointer)b->first + offset);
            last = first + count;
        }
        for (; first != last; ++first, ++where)
            new(placeholder(), where) T(*first);
    }

    template<typename T, typename Alloc>
    static inline void buffer_insert(buffer<T, Alloc>* b, T* where, size_t count) {
        where = buffer_insert_common(b, where, count);
        for (T* end = where + count; where != end; ++where)
            new(placeholder(), where) T();
    }

    template<typename T, typename Alloc, typename Param>
    static inline void buffer_append(buffer<T, Alloc>* b, const Param* param) {
        if (b->capacity != b->last) {
            new(placeholder(), b->last) T(*param);
            ++b->last;
        }
        else {
            buffer_insert(b, b->last, param, param + 1);
        }
    }

    template<typename T, typename Alloc>
    static inline void buffer_append(buffer<T, Alloc>* b) {
        if (b->capacity != b->last) {
            new(placeholder(), b->last) T();
            ++b->last;
        }
        else {
            buffer_insert(b, b->last, 1);
        }
    }

    template<typename T, typename Alloc>
    static inline T* buffer_erase(buffer<T, Alloc>* b, T* first, T* last) {
        typedef T* pointer;
        const size_t count = (last - first);
        for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest)
            move(*dest, *it);

        buffer_destroy_range(b->last - count, b->last);

        b->last -= count;
        return first;
    }

    template<typename T, typename Alloc>
    static inline T* buffer_erase_unordered(buffer<T, Alloc>* b, T* first, T* last) {
        typedef T* pointer;
        const size_t count = (last - first);
        const size_t tail = (b->last - last);
        pointer it = b->last - ((count < tail) ? count : tail);
        for (pointer end = b->last, dest = first; it != end; ++it, ++dest)
            move(*dest, *it);

        buffer_destroy_range(b->last - count, b->last);

        b->last -= count;
        return first;
    }

    template<typename T, typename Alloc>
    static inline void buffer_swap(buffer<T, Alloc>* b, buffer<T, Alloc>* other) {
        typedef T* pointer;
        const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity;
        b->first = other->first, b->last = other->last, b->capacity = other->capacity;
        other->first = tfirst, other->last = tlast, other->capacity = tcapacity;
    }
}

#endif


import assert from 'assert';
import moment from 'moment'; // jshint ignore:line
import React from 'react'; // jshint ignore:line
import ListLoading from 'misago/components/users/rank/list-loading' // jshint ignore:line
import List from 'misago/components/users/rank/list' // jshint ignore:line
import Pager from 'misago/components/users/rank/pager' // jshint ignore:line
import Root from 'misago/components/users/rank/root'; // jshint ignore:line
import misago from 'misago/index';
import reducer from 'misago/reducers/users';
import ajax from 'misago/services/ajax';
import polls from 'misago/services/polls';
import snackbar from 'misago/services/snackbar';
import store from 'misago/services/store';
import * as testUtils from 'misago/utils/test-utils';

let snackbarStore = null;

describe("Rank Users List", function() {
  afterEach(function() {
    testUtils.unmountComponents();
  });

  it("renders users", function(done) {
    /* jshint ignore:start */
    let users = [
      testUtils.mockUser({
        id: 123,
        title: "Lorem ipsum",
        status: {is_online: true},
        joined_on: moment()
      }),
      testUtils.mockUser({
        id: 122,
        status: {is_online: true},
        joined_on: moment()
      })
    ];

    let state = {
      count: 2,
      page: 1,
      pages: 2,
      page_range: [1, 2],
      first: 1,
      previous: null,
      next: 2,
      last: 2,
      before: 0,
      more: 1
    };

    testUtils.render(
      <List baseUrl='/users/'
            users={users}
            {...state} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .users-cards-list.ui-ready', function() {
      assert.ok(true, "component renders");

      assert.ok($('#test-mount .pager-undercontent').length,
        "paginator is rendered");

      assert.equal($('#test-mount .user-card').length, 2,
        "two users are rendered");

      done();
    });
  });
});

describe("Rank Users List Pager", function() {
  afterEach(function() {
    testUtils.unmountComponents();
  });

  it("renders", function(done) {
    /* jshint ignore:start */
    let state = {
      baseUrl: '/users/rank-slug/',

      count: 10,
      page: 2,
      pages: 3,
      page_range: [1, 2, 3],
      first: 1,
      previous: null,
      next: 3,
      last: 3,
      before: 10,
      more: 10
    };

    testUtils.render(
      <Pager {...state} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .pager-undercontent', function() {
      assert.ok(true, "component renders");

      assert.ok($('#test-mount .pager .previous').length, "prev page renders");
      assert.ok($('#test-mount .pager .next').length, "next page renders");
      assert.equal($('#test-mount .pager-progress-bar li').length, 3,
        "progress bar renders");

      assert.equal($('#test-mount .pager-progress-bar .active').text().trim(),
        '2',
        "valid page is active in progress bar");

      done();
    });
  });

  it("renders without next page", function(done) {
    /* jshint ignore:start */
    let state = {
      baseUrl: '/users/rank-slug/',

      count: 10,
      page: 3,
      pages: 3,
      page_range: [1, 2, 3],
      first: 1,
      previous: null,
      next: null,
      last: null,
      before: 10,
      more: 0
    };

    testUtils.render(
      <Pager {...state} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .pager-undercontent', function() {
      assert.ok(true, "component renders");

      assert.ok($('#test-mount .pager .previous').length, "prev page renders");
      assert.ok(!$('#test-mount .pager .next').length, "next not rendering");
      assert.equal($('#test-mount .pager-progress-bar li').length, 3,
        "progress bar renders");

      assert.equal($('#test-mount .pager-progress-bar .active').text().trim(),
        '3',
        "valid page is active in progress bar");

      done();
    });
  });

  it("renders without prev page", function(done) {
    /* jshint ignore:start */
    let state = {
      baseUrl: '/users/rank-slug/',

      count: 10,
      page: 1,
      pages: 3,
      page_range: [1, 2, 3],
      first: null,
      previous: null,
      next: 2,
      last: 3,
      before: 0,
      more: 10
    };

    testUtils.render(
      <Pager {...state} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .pager-undercontent', function() {
      assert.ok(true, "component renders");

      assert.ok(!$('#test-mount .pager .previous').length,
        "prev page is not rendering");
      assert.ok($('#test-mount .pager .next').length, "next page renders");
      assert.equal($('#test-mount .pager-progress-bar li').length, 3,
        "progress bar renders");

      assert.equal($('#test-mount .pager-progress-bar .active').text().trim(),
        '1',
        "valid page is active in progress bar");

      done();
    });
  });
});

describe("Rank Users List Loading", function() {
  afterEach(function() {
    testUtils.unmountComponents();
  });

  it("renders", function(done) {
    /* jshint ignore:start */
    testUtils.render(<ListLoading />);
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .users-cards-list', function() {
      assert.ok(true, "component renders");

      done();
    });
  });
});

describe("Rank Users List Root", function() {
  beforeEach(function() {
    snackbarStore = testUtils.snackbarStoreMock();
    snackbar.init(snackbarStore);

    polls.init(ajax, snackbar);

    testUtils.contextGuest(misago);

    misago._context = Object.assign(misago._context, {
      USERS_LIST_URL: '/users/',
      USERS_API: '/test-api/users/',

      USERS_LISTS: [
        {
          component: "rank",
          id: 424,
          name: "Forum team",
          slug: 'forum-team',
          css_class: 'forum-team',
          description: {
            plain: "This is forum team rank.",
            html: "
This is forum team rank.
"
          }
        }
      ]
    });

    store.constructor();
    store.addReducer('users', reducer, []);
    store.addReducer('auth', function(state, action) {
      if (action || true) {
        return {};
      }
    }, {});
    store.addReducer('tick', function(state, action) {
      if (action || true) {
        return {'tick': 123};
      }
    }, {});

    store.init();
  });

  afterEach(function() {
    testUtils.unmountComponents();
    testUtils.snackbarClear(snackbar);
    $.mockjax.clear();
  });

  it("renders preloaded", function(done) {
    let data = {
      results: [
        testUtils.mockUser({
          id: 123,
          title: "Lorem ipsum",
          status: {is_online: true}
        }),
        testUtils.mockUser({
          id: 122,
          status: {is_online: true}
        })
      ],

      count: 10,
      page: 1,
      pages: 1,
      page_range: [1],
      first: null,
      previous: null,
      next: null,
      last: null,
      before: 0,
      more: 0
    };

    $.mockjax({
      url: '/test-api/users/?rank=424&page=1',
      status: 200,
      responseText: data
    });

    misago._context.USERS = data;

    /* jshint ignore:start */
    let rank = {
      id: 424,
      name: "Forum team",
      slug: 'forum-team',
      css_class: 'forum-team',
      description: {
        plain: "This is forum team rank.",
        html: "
This is forum team rank.
"
      }
    };

    testUtils.render(
      <Root user={misago._context.user}
            users={[]}
            tick={123}
            route={{rank: rank}}
            params={{}} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .users-cards-list.ui-ready', function() {
      assert.ok(true, "component renders");

      assert.equal($('#test-mount p.test-description').text().trim(),
        "This is forum team rank.",
        "rank description was displayed");

      done();
    });
  });

  it("loads", function(done) {
    let data = {
      results: [
        testUtils.mockUser({
          id: 123,
          title: "Lorem ipsum",
          status: {is_online: true}
        }),
        testUtils.mockUser({
          id: 122,
          status: {is_online: true}
        })
      ],

      count: 10,
      page: 1,
      pages: 1,
      page_range: [1],
      first: null,
      previous: null,
      next: null,
      last: null,
      before: 0,
      more: 0
    };

    $.mockjax({
      url: '/test-api/users/?rank=424&page=1',
      status: 200,
      responseText: data
    });

    /* jshint ignore:start */
    let rank = {
      id: 424,
      name: "Forum team",
      slug: 'forum-team',
      css_class: 'forum-team',
      description: {
        plain: "This is forum team rank.",
        html: "
This is forum team rank.
"
      }
    };

    testUtils.render(
      <Root user={misago._context.user}
            users={[]}
            tick={123}
            route={{rank: rank}}
            params={{}} />
    );
    /* jshint ignore:end */

    testUtils.onElement('#test-mount .users-cards-list.ui-ready', function() {
      assert.ok(true, "component renders");

      assert.equal($('#test-mount p.test-description').text().trim(),
        "This is forum team rank.",
        "rank description was displayed");

      done();
    });
  });

  it("handles backend error", function(done) {
    $.mockjax({
      url: '/test-api/users/?rank=424&page=1',
      status: 500
    });

    /* jshint ignore:start */
    let rank = {
      id: 424,
      name: "Forum team",
      slug: 'forum-team',
      css_class: 'forum-team',
      description: {
        plain: "This is forum team rank.",
        html: "
This is forum team rank.
"
      }
    };

    testUtils.render(
      <Root user={misago._context.user}
            users={[]}
            tick={123}
            route={{rank: rank}}
            params={{}} />
    );
    /* jshint ignore:end */

    snackbarStore.callback(function(message) {
      assert.deepEqual(message, {
        message: "Unknown error has occured.",
        type: 'error'
      }, "error message was shown");

      done();
    });
  });
});


/*
Copyright The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Code generated by lister-gen. DO NOT EDIT.

package v1alpha1

// VolumeAttachmentListerExpansion allows custom methods to be added to
// VolumeAttachmentLister.
type VolumeAttachmentListerExpansion interface{}


CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/AFNetworking
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/AFNetworking" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/BAButton" "${PODS_ROOT}/Headers/Public/DZNEmptyDataSet" "${PODS_ROOT}/Headers/Public/FBRetainCycleDetector" "${PODS_ROOT}/Headers/Public/IQKeyboardManager" "${PODS_ROOT}/Headers/Public/JMRoundedCorner" "${PODS_ROOT}/Headers/Public/MBProgressHUD" "${PODS_ROOT}/Headers/Public/MJExtension" "${PODS_ROOT}/Headers/Public/MJRefresh" "${PODS_ROOT}/Headers/Public/MLeaksFinder" "${PODS_ROOT}/Headers/Public/Masonry" "${PODS_ROOT}/Headers/Public/NullSafe" "${PODS_ROOT}/Headers/Public/SDAutoLayout" "${PODS_ROOT}/Headers/Public/SDWebImage"
OTHER_LDFLAGS = -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration"
PODS_BUILD_DIR = $BUILD_DIR
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES


wget https://download.visinf.tu-darmstadt.de/data/denoising_datasets/Set12.zip
unzip Set12.zip
rm Set12.zip


<?php

/*
 * Copyright (C) 2009 - 2019 Internet Neutral Exchange Association Company Limited By Guarantee.
 * All Rights Reserved.
 *
 * This file is part of IXP Manager.
 *
 * IXP Manager is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version v2.0 of the License.
 *
 * IXP Manager is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GpNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License v2.0
 * along with IXP Manager.  If not, see:
 *
 * http://www.gnu.org/licenses/gpl-2.0.html
 */

namespace Repositories;

use DB;

use Doctrine\ORM\EntityRepository;

use Entities\{
    Layer2Address as Layer2AddressEntity,
    Router as RouterEntity,
    Vlan as VlanEntity,
    VlanInterface as VlanInterfaceEntity
};

use IXP\Exceptions\GeneralException as IXP_Exception;

/**
 * VlanInterface
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class VlanInterface extends EntityRepository
{

    /**
     * Utility function to provide an array of all VLAN interfaces on a given
     * VLAN for a given protocol.
     *
     * Returns an array of elements such as:
     *
     *     [
     *         [cid] => 999
     *         [cname] => Customer Name
     *         [abrevcname] => Abbreviated Customer Name
     *         [cshortname] => shortname
     *         [autsys] => 65500
     *         [gmaxprefixes] => 20        // from cust table (global)
     *         [peeringmacro] => ABC
     *         [peeringmacrov6] => ABC
     *         [vid]        => 2
     *         [vtag]       => 10,
     *         [vname]      => "Peering LAN #1
     *         [viid] => 120
     *         [vliid] => 159
     *         [canping] => 1
     *         [enabled] => 1              // VLAN interface enabled for requested protocol?
     *         [address] => 192.0.2.123    // assigned address for requested protocol?
     *         [monitorrcbgp] => 1
     *         [bgpmd5secret] => qwertyui  // MD5 for requested protocol
     *         [hostname] => hostname      // Hostname
     *         [maxbgpprefix] => 20        // VLAN interface max prefixes
     *         [as112client] => 1          // if the member is an as112 client or not
     *         [rsclient] => 1             // if the member is a route server client or not
     *         [rsmorespecifics] => 0/1    // if IRRDB filtering should allow more specifics
     *         [busyhost]
     *         [sid]
     *         [sname]
     *         [cabid]
     *         [cabname]
     *         [location_name]
     *         [location_tag]
     *         [location_shortname]
     *     ]
     *
     * @param \Entities\Vlan $vlan The VLAN
     * @param int $proto Either 4 or 6
     * @param int $pistatus The status of the physical interface
     * @return array As defined above.
     * @throws IXP_Exception On bad / no protocol
     */
    public function getForProto( $vlan, $proto, $pistatus = \Entities\PhysicalInterface::STATUS_CONNECTED )
    {
        if( !in_array( $proto, [ 4, 6 ] ) )
            throw new IXP_Exception( 'Invalid protocol specified' );

        $qstr = "SELECT c.id              AS cid,
                        c.name            AS cname,
                        c.abbreviatedName AS abrevcname,
                        c.shortname       AS cshortname,
                        c.autsys          AS autsys,
                        c.maxprefixes     AS gmaxprefixes,
                        c.peeringmacro    AS peeringmacro,
                        c.peeringmacrov6  AS peeringmacrov6,

                        v.id                 AS vid,
                        v.number             AS vtag,
                        v.name               AS vname,
                        vi.id                AS viid,

                        vli.id AS vliid,

                        vli.ipv{$proto}enabled      AS enabled,
                        vli.ipv{$proto}hostname     AS hostname,
                        vli.ipv{$proto}monitorrcbgp AS monitorrcbgp,
                        vli.ipv{$proto}bgpmd5secret AS bgpmd5secret,
                        vli.maxbgpprefix            AS maxbgpprefix,
                        vli.as112client             AS as112client,
                        vli.rsclient                AS rsclient,
                        vli.busyhost                AS busyhost,
                        vli.irrdbfilter             AS irrdbfilter,
                        vli.rsmorespecifics         AS rsmorespecifics,
                        vli.ipv{$proto}canping      AS canping,

                        addr.address AS address,

                        s.id   AS sid,
                        s.name AS sname,

                        cab.id   AS cabid,
                        cab.name AS cabname,

                        l.id        AS location_id,
                        l.name      AS location_name,
                        l.shortname AS location_shortname,
                        l.tag       AS location_tag

                    FROM Entities\VlanInterface vli
                        LEFT JOIN vli.VirtualInterface vi
                        LEFT JOIN vli.IPv{$proto}Address addr
                        LEFT JOIN vi.Customer c
                        LEFT JOIN vi.PhysicalInterfaces pi
                        LEFT JOIN pi.SwitchPort sp
                        LEFT JOIN sp.Switcher s
                        LEFT JOIN s.Cabinet cab
                        LEFT JOIN cab.Location l
                        LEFT JOIN vli.Vlan v
                    WHERE
                        v = :vlan
                        AND " . Customer::DQL_CUST_ACTIVE     . "
                        AND " . Customer::DQL_CUST_CURRENT    . "
                        AND " . Customer::DQL_CUST_TRAFFICING . "
                        AND pi.status = :pistatus

                    GROUP BY
                        vli.id, c.id, c.name, c.abbreviatedName, c.shortname, c.autsys,
                        c.maxprefixes, c.peeringmacro, c.peeringmacrov6,
                        vli.ipv{$proto}enabled, addr.address, vli.ipv{$proto}bgpmd5secret, vli.maxbgpprefix,
                        vli.ipv{$proto}hostname, vli.ipv{$proto}monitorrcbgp, vli.busyhost,
                        vli.as112client, vli.rsclient, vli.irrdbfilter, vli.ipv{$proto}canping,
                        s.id, s.name,
                        cab.id, cab.name,
                        l.name, l.shortname, l.tag
                        ";

        $qstr .= " ORDER BY c.autsys ASC, vli.id ASC";

        $q = $this->getEntityManager()->createQuery( $qstr );
        $q->setParameter( 'vlan', $vlan );
        $q->setParameter( 'pistatus', $pistatus );
        return $q->getArrayResult();
    }

    /**
     * Utility function to provide an array of VLAN interface objects on a given VLAN.
     *
     * @param \Entities\Vlan $vlan The VLAN to gather VlanInterfaces for
     * @return \Entities\VlanInterface[] Indexed by VlanInterface ID
     */
    public function getObjectsForVlan( $vlan, $protocol = null )
    {
        if( in_array( $protocol, [ 4, 6 ] ) ) {
            $pq = " AND vli.ipv{$protocol}enabled = 1";
        } else

        $qstr = "SELECT vli
                    FROM Entities\VlanInterface vli
                        JOIN vli.Vlan v
                        JOIN vli.VirtualInterface vi
                        JOIN vi.PhysicalInterfaces pi
                        JOIN vi.Customer c

                    WHERE
                        v = :vlan
                        AND " . Customer::DQL_CUST_ACTIVE     . "
                        AND " . Customer::DQL_CUST_CURRENT    . "
                        AND " . Customer::DQL_CUST_TRAFFICING . "
                        AND " . Customer::DQL_CUST_EXTERNAL   . "
                        AND pi.status = " . \Entities\PhysicalInterface::STATUS_CONNECTED . ( $pq ?? '' ) . "

                    ORDER BY c.name ASC";

        $q = $this->getEntityManager()->createQuery( $qstr );
        $q->setParameter( 'vlan', $vlan );

        $vlis = [];
        foreach( $q->getResult() as $vli )
            $vlis[ $vli->getId() ] = $vli;

        return $vlis;
    }

    /**
     * Utility function to provide an array of all VLAN interface objects for a given
     * customer at an optionally given IXP.
     *
     * @param \Entities\Customer $customer The customer
     * @return \Entities\VlanInterface[] Index by the VlanInterface ID
     */
    public function getForCustomer( $customer )
    {
        $qstr = "SELECT vli
                    FROM Entities\\VlanInterface vli
                        JOIN vli.VirtualInterface vi
                        JOIN vi.Customer c
                        JOIN vli.Vlan v
                    WHERE c = :customer
                    ORDER BY v.number";

        $q = $this->getEntityManager()->createQuery( $qstr );
        $q->setParameter( 'customer', $customer );

        $vlis = [];

        foreach( $q->getResult() as $vli ) {
            $vlis[ $vli->getId() ] = $vli;
        }

        return $vlis;
    }

    /**
     * Utility function to get and return active VLAN interfaces on the requested protocol
     * suitable for route collector / server configuration.
     *
     * Sample return:
     *
     *     [
     *         [cid] => 999
     *         [cname] => Customer Name
     *         [cshortname] => shortname
     *         [autsys] => 65000
     *         [peeringmacro] => QWE              // or AS65500 if not defined
     *         [vliid] => 159
     *         [fvliid] => 00159                  // formatted %05d
     *         [address] => 192.0.2.123
     *         [bgpmd5secret] => qwertyui         // or false
     *         [as112client] => 1                 // if the member is an as112 client or not
     *         [rsclient] => 1                    // if the member is a route server client or not
     *         [maxprefixes] => 20
     *         [irrdbfilter] => 0/1               // if IRRDB filtering should be applied
     *         [rsmorespecifics] => 0/1           // if IRRDB filtering should allow more specifics
     *         [location_name] => Interxion DUB1
     *         [location_shortname] => IX-DUB1
     *         [location_tag] => ix1
     *     ]
     *
     * @param Vlan $vlan
     * @return array As defined above
     * @throws \Exception
     */
    public function sanitiseVlanInterfaces( VlanEntity $vlan, int $protocol = 4, int $target = RouterEntity::TYPE_ROUTE_SERVER, bool $quarantine = false ): array {

        $ints = $this->getForProto( $vlan, $protocol,
            $quarantine  ? \Entities\PhysicalInterface::STATUS_QUARANTINE : \Entities\PhysicalInterface::STATUS_CONNECTED
        );

        $newints = [];

        foreach( $ints as $int )
        {
            if( !$int['enabled'] ) {
                continue;
            }

            $int['protocol'] = $protocol;

            // don't need this anymore:
            unset( $int['enabled'] );

            if( $target == RouterEntity::TYPE_ROUTE_SERVER && !$int['rsclient'] ) {
                continue;
            }

            if( $target == RouterEntity::TYPE_AS112 && !$int['as112client'] ) {
                continue;
            }

            $int['fvliid'] = sprintf( '%04d', $int['vliid'] );

            if( $int['maxbgpprefix'] && $int['maxbgpprefix'] > $int['gmaxprefixes'] ) {
                $int['maxprefixes'] = $int['maxbgpprefix'];
            } else {
                $int['maxprefixes'] = $int['gmaxprefixes'];
            }

            if( !$int['maxprefixes'] ) {
                $int['maxprefixes'] = 250;
            }

            unset( $int['gmaxprefixes'] );
            unset( $int['maxbgpprefix'] );

            if( $protocol == 6 && $int['peeringmacrov6'] ) {
                $int['peeringmacro'] = $int['peeringmacrov6'];
            }

            if( !$int['peeringmacro'] ) {
                $int['peeringmacro'] = 'AS' . $int['autsys'];
            }

            unset( $int['peeringmacrov6'] );

            if( !$int['bgpmd5secret'] ) {
                $int['bgpmd5secret'] = false;
            }

            $int['allpeeringips'] = $this->getAllIPsForASN( $vlan, $int['autsys'], $protocol );

            if( $int['irrdbfilter'] ) {
                $int['irrdbfilter_prefixes'] = d2r( 'IrrdbPrefix' )->getForCustomerAndProtocol( $int[ 'cid' ], $protocol, true );
                $int['irrdbfilter_asns'    ] = d2r( 'IrrdbAsn'    )->getForCustomerAndProtocol( $int[ 'cid' ], $protocol, true );
            }

            $newints[ $int['address'] ] = $int;
        }

        return $newints;
    }

    /**
     * Find all IP addresses on a given VLAN for a given ASN and protocol.
     *
     * This is used (for example) when generating router configuration
     * which prevents next-hop hijacking but allows the same ASN to
     * set its other IPs as the next hop.
     *
     * @param VlanEntity $v
     * @param int $asn
     * @param int $proto
     * @return array Array of IP addresses [ '192.0.2.2', '192.0.2.23', ]
     * @throws \Exception
     */
    public function getAllIPsForASN( VlanEntity $v, int $asn, int $proto ): array
    {
        if( !in_array( $proto, [4,6] ) ) {
            throw new \Exception( 'Invalid inet protocol' );
        }

        $ipe = "IPv{$proto}Address";

        $dql = "SELECT ip.address AS ipaddress

                    FROM Entities\Vlan v
                        LEFT JOIN v.VlanInterfaces vli
                        LEFT JOIN vli.{$ipe} ip
                        LEFT JOIN vli.VirtualInterface vi
                        LEFT JOIN vi.Customer c

                    WHERE c.autsys = :asn AND v = :vlan";

        $q = $this->getEntityManager()->createQuery( $dql )
            ->setParameter( 'asn', $asn )
            ->setParameter( 'vlan', $v );

        $ips = array_column( $q->getScalarResult(), 'ipaddress' );
        $vips = [];

        foreach( $ips as $ip ) {
            if( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
                $vips[] = $ip;
            }
        }

        return $vips;
    }

    /**
     * Provide array of vlan interfaces for the list Action
     *
     * @param int $id The VlanInterface to find
     * @return array array of vlan interfaces
     */
    public function getForList( int $id = null )
    {
        $dql = "SELECT vli.id AS id, vli.mcastenabled AS mcastenabled,
                 vli.ipv4enabled AS ipv4enabled, vli.ipv4hostname AS ipv4hostname, vli.ipv4canping AS ipv4canping,
                     vli.ipv4monitorrcbgp AS ipv4monitorrcbgp, vli.ipv4bgpmd5secret AS ipv4bgpmd5secret,
                 vli.ipv6enabled AS ipv6enabled, vli.ipv6hostname AS ipv6hostname, vli.ipv6canping AS ipv6canping,
                     vli.ipv6monitorrcbgp AS ipv6monitorrcbgp, vli.ipv6bgpmd5secret AS ipv6bgpmd5secret,
                 vli.irrdbfilter AS irrdbfilter, vli.bgpmd5secret AS bgpmd5secret, vli.maxbgpprefix AS maxbgpprefix,
                 vli.as112client AS as112client, vli.busyhost AS busyhost, vli.notes AS notes,
                 vli.rsclient AS rsclient,
                 ip4.address AS ipv4, ip6.address AS ipv6,
                 v.id AS vlanid, v.name AS vlan,
                 vi.id AS vintid,
                 c.name AS customer, c.id AS custid
                    FROM \\Entities\\VlanInterface vli
                        LEFT JOIN vli.VirtualInterface vi
                        LEFT JOIN vli.Vlan v
                        LEFT JOIN vli.IPv4Address ip4
                        LEFT JOIN vli.IPv6Address ip6
                        LEFT JOIN vi.Customer c";

        if( $id ){
            $dql .= " WHERE vli.id = $id ";
        }

        $q = $this->getEntityManager()->createQuery( $dql );
        return $q->getArrayResult();
    }

    /**
     * Get vli id / mac address mapping from macaddress table for sflow data processing
     *
     * Returns a hash as follows:
     *
     *     {
     *         '$infrastructure' => {
     *             '$vlan' => {
     *                '$mac' => $vliid
     *                '$mac' => $vliid
     *             }
     *         }
     *     }
     *
     * @return mixed
     */
    public function sflowLearnedMacsHash(): array
    {
        return $this->getEntityManager()->createQuery(
            "SELECT DISTINCT vli.id AS vliid, ma.mac AS mac, vl.number as tag, i.id as infrastructure
                    FROM Entities\VirtualInterface vi
                        LEFT JOIN vi.VlanInterfaces vli
                        JOIN vi.MACAddresses ma
                        LEFT JOIN vli.Vlan vl
                        LEFT JOIN vl.Infrastructure i
                    WHERE ma.mac IS NOT NULL
                        AND vli.id IS NOT NULL
                    ORDER BY vliid"
        )->getArrayResult();
    }

    /**
     * Get vli id / mac address mapping from macaddress table for sflow data processing
     *
     * Returns a hash as follows:
     *
     *     {
     *         '$infrastructure' => {
     *             '$vlan' => {
     *                '$mac' => $vliid
     *                '$mac' => $vliid
     *             }
     *         }
     *     }
     *
     * @return mixed
     */
    public function sflowConfiguredMacsHash(): array
    {
        return $this->getEntityManager()->createQuery(
            "SELECT DISTINCT vli.id AS vliid, l2a.mac AS mac, vl.number as tag, i.id as infrastructure
                    FROM Entities\VlanInterface vli
                        LEFT JOIN vli.VirtualInterface vi
                        LEFT JOIN vli.layer2Addresses l2a
                        LEFT JOIN vli.Vlan vl
                        LEFT JOIN vl.Infrastructure i
                    WHERE l2a.mac IS NOT NULL
                    ORDER BY vliid"
        )->getArrayResult();
    }

    /**
     * Utility function to copy all l2a's from one vli to another
     *
     * @param VlanInterfaceEntity $s Source VLI for l2a's
     * @param VlanInterfaceEntity $d Destinatin VLI for copied l2a's
     * @return VlanInterface
     */
    public function copyLayer2Addresses( VlanInterfaceEntity $s, VlanInterfaceEntity $d ): VlanInterface {
        foreach( $s->getLayer2Addresses() as $l2a ) {
            $n = new Layer2AddressEntity();
            $n->setVlanInterface( $d );
            $d->addLayer2Address( $n );
            $n->setMac( $l2a->getMac() );
            $this->getEntityManager()->persist( $n );
        }

        return $this;
    }

    /**
     * Get statistics of RS clients / total on a per VLAN basis
     *
     * Returns an array of objects such as:
     *
     *     [
     *         {
     *             +"vlanname": "Peering VLAN #1",
     *             ++"overall_count": 60,
     *             ++"rsclient_count": "54",
     *         }
     *     ]
     *
     * @return array
     */
    public function getRsClientUsagePerVlan(): array
    {
        return DB::select('SELECT v.name AS vlanname, COUNT(vli.id) AS overall_count, SUM(vli.rsclient = 1) AS rsclient_count
            FROM `vlaninterface` AS vli
            LEFT JOIN virtualinterface AS vi ON vli.virtualinterfaceid = vi.id
            LEFT JOIN cust AS c ON vi.custid = c.id
            LEFT JOIN vlan AS v ON vli.vlanid = v.id
            WHERE v.`private` = 0 AND c.type IN (1,4)
            GROUP BY vlanname'
        );
    }

    /**
     * Get statistics of ipv6 enabled / total on a per VLAN basis
     *
     * Returns an array of objects such as:
     *
     *     [
     *         {
     *             +"vlanname": "Peering VLAN #1",
     *             ++"overall_count": 60,
     *             ++"ipv6_count": "54",
     *         }
     *     ]
     *
     * @return array
     */
    public function getIPv6UsagePerVlan(): array
    {
        return DB::select('SELECT v.name AS vlanname, COUNT(vli.id) AS overall_count, SUM(vli.ipv6enabled = 1) AS ipv6_count
            FROM `vlaninterface` AS vli
            LEFT JOIN virtualinterface AS vi ON vli.virtualinterfaceid = vi.id
            LEFT JOIN cust AS c ON vi.custid = c.id
            LEFT JOIN vlan AS v ON vli.vlanid = v.id
            WHERE v.`private` = 0 AND c.type IN (1,4)
            GROUP BY vlanname'
        );
    }
}


# Receding Horizon Next Best View Planning

The next best view planner is a real-time capable exploration path planner. From the current pose it expands a tree to find a next pose that gives a high exploration gain. This gain reflects the exploration of space that is not yet (sufficiently) known. As the vehicle proceeds on the path, the tree is recomputed, taking into account the new information from the sensor.

This README gives a short overview. For more information refer to the [wiki](https://github.com/ethz-asl/nbvplanner/wiki).

# Planner installation and execution

To run the current version, compile the package nbvplanner. To get it navigate to the source folder of your ros workspace:

```sh
git clone https://github.com/ethz-asl/nbvplanner.git
cd nbvplanner
git submodule init --
git submodule sync --recursive
git submodule update --recursive
cd ..
```

Moreover, make sure you have all the necessary libraries:
```sh
apt-get install ros-<distro>-octomap-*
apt-get install python-catkin-tools
catkin build
```

For a simulation demo launch

```sh
roslaunch interface_nbvp_rotors flat_exploration.launch
```

Tested under ROS Indigo and Jade.

Further instructions for the visualization of the exploration progress, as well as more demo scenarios and descriptions of the parameters can be found in the [wiki](https://github.com/ethz-asl/nbvplanner/wiki).

If you use this software in a scientific publication, please cite the following paper:
```
@inproceedings{bircher2016receding,
  title={Receding horizon "next-best-view" planner for 3D exploration},
  author={Bircher, Andreas and Kamel, Mina and Alexis, Kostas and Oleynikova, Helen and Siegwart, Roland},
  booktitle={2016 IEEE International Conference on Robotics and Automation (ICRA)},
  pages={1462--1468},
  year={2016},
  organization={IEEE}
}
```

# Credits

This algorithm was developed by [Andreas Bircher](mailto:bircher@gmx.ch) with the help and support of the members of the [Autonomous Systems Lab](http://www.asl.ethz.ch). The work was supported by the European Commission-funded project [AEROWORKS](http://www.aeroworks2020.eu/).

# Contact

You can contact us for any question or remark:
* [Andreas Bircher](mailto:bircher@gmx.ch)
* [Kostas Alexis](mailto:konstantinos.alexis@mavt.ethz.ch)


<!DOCTYPE html>

    <title>AnyPlasticNodeDescription Protocol Reference</title>
    <link rel="stylesheet" type="text/css" href="../css/jazzy.css" />
    <link rel="stylesheet" type="text/css" href="../css/highlight.css" />
    <meta charset='utf-8'>

Katana Docs (99% documented)

View on GitHub

        Katana Reference

        AnyPlasticNodeDescription Protocol Reference

            Classes

                EmptySideEffectDependencyContainer

                Node

                PlasticNode

                PlasticView

                Renderer

                StateMockProvider

                Store

                ViewsContainer

            Enums

                AnimationType

                AsyncActionState

                EmptyKeys

            Extensions

                Array

                CGSize

                UIView

            Protocols

                Action

                ActionWithSideEffect

                AnyAsyncAction

                AnyConnectedNodeDescription

                AnyNode

                AnyNodeDescription

                AnyNodeDescriptionProps

                AnyNodeDescriptionWithChildren

                AnyNodeDescriptionWithRefProps

                AnyPlasticNodeDescription

                AnyPlatformNativeViewWithRef

                AnyStore

                AsyncAction

                Childrenable

                ConnectedNodeDescription

                LinkeableAction

                NativeViewRef

                NativeViewWithRef

                NodeDescription

                NodeDescriptionProps

                NodeDescriptionState

                NodeDescriptionWithChildren

                NodeDescriptionWithRef

                NodeDescriptionWithRefProps

                PlasticNodeDescription

                PlasticReferenceSizeable

                PlatformNativeView

                SideEffectDependencyContainer

                State

            Structs

                ActionLinker

                ActionLinks

                Anchor

                – Kind

                Animation

                AnimationContainer

                AnimationOptions

                AnimationProps

                ChildrenAnimations

                EdgeInsets

                EmptyProps

                EmptyState

                Size

                Value

            Typealiases

                AnimationPropsTransformer

                AnyRefCallbackClosure

                NodeUpdateCompletion

                RefCallbackClosure

                StoreDispatch

                StoreListener

                StoreMiddleware

                StoreUnsubscribe

            Associated Types

                PropsType

AnyPlasticNodeDescription

public protocol AnyPlasticNodeDescription

Type Erasure for PlasticNodeDescription

                    anyLayout(views:props:state:)

Implements the layout logic of the node description

See also

    PlasticNodeDescription, layout(views:props:state:) method

Declaration

Swift

static func anyLayout(views: Any, props: Any, state: Any)

                        Show on GitHub

© 2017 Bending Spoons Team. All rights reserved. (Last updated: 2017-07-24)

Generated by jazzy ♪♫ v0.7.4, a Realm project.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<link rel="icon" type="image/x-icon" href="favicon.ico" />
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>chigraph: lib/core/include/chi/Fwd.hpp File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>

<link href="navtree.css" rel="stylesheet" type="text/css"/>

<link href="search/search.css" rel="stylesheet" type="text/css"/>

<link href="doxygen.css" rel="stylesheet" type="text/css" />

chigraph
    master

Systems programming language written for beginners in LLVM

Namespaces

Fwd.hpp File Reference

Forward declares all the chigraph data types.
More...

#include "chi/Support/Fwd.hpp"

   Include dependency graph for Fwd.hpp:

This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.

   This graph shows which files directly or indirectly include this file:

This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.

Go to the source code of this file.

Namespaces

  	chi

 	The namespace where chigraph lives.

Detailed Description

Forward declares all the chigraph data types.

Definition in file Fwd.hpp.

lib

core

include

chi

Fwd.hpp

Generated on Sat Sep 16 2017 17:41:35 for chigraph by

     1.8.13


# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

# This file contains command-line options that the VB
# command line compiler (VBC) will process as part
# of every compilation, unless the "/noconfig" option
# is specified.

# Reference the common Framework libraries
/r:Accessibility.dll
/r:System.Configuration.dll
/r:System.Configuration.Install.dll
/r:System.Data.dll
/r:System.Data.OracleClient.dll
/r:System.Deployment.dll
/r:System.Design.dll
/r:System.DirectoryServices.dll
/r:System.dll
/r:System.Drawing.Design.dll
/r:System.Drawing.dll
/r:System.EnterpriseServices.dll
/r:System.Management.dll
/r:System.Messaging.dll
/r:System.Runtime.Remoting.dll
/r:System.Runtime.Serialization.Formatters.Soap.dll
/r:System.Security.dll
/r:System.ServiceProcess.dll
/r:System.Transactions.dll
/r:System.Web.dll
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.dll
/r:System.XML.dll

/r:System.Workflow.Activities.dll
/r:System.Workflow.ComponentModel.dll
/r:System.Workflow.Runtime.dll
/r:System.Runtime.Serialization.dll
/r:System.ServiceModel.dll

/r:System.Core.dll
/r:System.Xml.Linq.dll
/r:System.Data.Linq.dll
/r:System.Data.DataSetExtensions.dll
/r:System.Web.Extensions.dll
/r:System.Web.Extensions.Design.dll
/r:System.ServiceModel.Web.dll

# Import System and Microsoft.VisualBasic
/imports:System
/imports:Microsoft.VisualBasic
/imports:System.Linq
/imports:System.Xml.Linq

/optioninfer+


<?xml version="1.0"?>
<doc>
    <assembly>
        <name>Google.Apis.PlatformServices</name>
    </assembly>
    <members>
        <member name="T:Google.Apis.Util.Store.PasswordVaultDataStore">

            Credentials store that implements <see cref="T:Google.Apis.Util.Store.IDataStore"/>.
            This store saves all keys encrypted in a <see cref="T:Windows.Security.Credentials.PasswordVault"/>

        </member>
        <member name="M:Google.Apis.Util.Store.PasswordVaultDataStore.StoreAsync``1(System.String,``0)">
            Adds a new key to the password vault.
        </member>
        <member name="M:Google.Apis.Util.Store.PasswordVaultDataStore.DeleteAsync``1(System.String)">
            Deletes a given key from the password vault.
        </member>
        <member name="M:Google.Apis.Util.Store.PasswordVaultDataStore.GetAsync``1(System.String)">

            Gets a specific key from the password vault. Returns <c>default(T)</c> if there is no matching entry.

        </member>
        <member name="M:Google.Apis.Util.Store.PasswordVaultDataStore.ClearAsync">
            Removes all values from the password vault.
        </member>
    </members>
</doc>


tensorflowjs_converter \
  --input_format=tf_saved_model \
  --output_format=tfjs_graph_model \
  --signature_name=serving_default \
  --saved_model_tags=serve \
  saved_model \
  tfjs_model