import React from 'react';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import Tooltip from '@material-ui/core/Tooltip';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import Grid from '@material-ui/core/Grid';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import LaunchIcon from '@material-ui/icons/Launch';
import CloseIcon from '@material-ui/icons/Close';
import MoreIcon from '@material-ui/icons/More';
import Chip from '@material-ui/core/Chip';
import i18n from '../../i18n';
import ChaincodeInstall from "../chaincode/install";
import ChaincodeInstantiate from "../chaincode/instantiate";
import ChaincodeExecute from "../chaincode/execute";
import ChaincodeEvent from "../chaincode/event";
import ChannelCreate from "../channel/create";
import ChannelJoin from "../channel/join";
import LedgerDetail from "../ledger/detail";
import { cntTrim, getCurrIDConn, refreshNetwork } from "../../common/utils";
import { log } from "../../common/log";
import * as CONST from "../../common/constants";

const styles = (theme) => ({
    card: {
        width: "100%",
    },
    highLightCard: {
        width: "100%",
        backgroundColor: "#cfe8fc"
    },
    cardContent: {
        //display: 'flex',
        //flexWrap: 'wrap',
        paddingLeft: 12,
        paddingTop: 6,
        paddingBottom: 6,
        paddingRight: 6,
    },
    bullet: {
        display: 'inline-block',
        margin: '0 2px',
        transform: 'scale(0.8)',
    },
    title: {
        fontSize: 13,
        fontWeight: 600
    },
    normal: {
        fontSize: 13,
    },
    peer_status_fine: {
        background: "#12C412",
    },
    peer_status_error: {
        background: "#A12222",
    },
    timeFlag: {
        fontSize: 11,
        marginLeft: "auto",
    },
    fieldDetail: {
        fontSize: 11,
    },
    tooltipTableWrapper: {
        maxHeight: 450,
        overflow: 'auto',
    },
    detailTableWrapper: {
        maxHeight: 450,
        overflow: 'auto',
    },
    detailHeaderFocused: {
        marginTop: 10,
        marginBottom: 10
    },
    detailHeaderWidget: {
        marginTop: 0,
        marginBottom: 0}
});

const HtmlTooltip = withStyles(theme => ({
    tooltip: {
        backgroundColor: "#f5f5f9",
        color: "rgba(0, 0, 0, 0.87)",
        maxWidth: 650,
        width: 650,
        fontSize: theme.typography.pxToRem(12),
        border: "1px solid #dadde9"
    },
}))(Tooltip);

class PeerOverview extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            ...props,
            // peer, peers, peerStatuses, channelLedgers, channelOrderers, channelChaincodes, channelAnchorPeers
            // onFocus: props.onFocus
            // onLeaveFocus: props.onLeaveFocus
            // isFocus: props.isFocus

            openInstallChaincode: false,
            openInstantiateChaincode: false,
            openExecuteChaincode: false,
            openLedgerDetail: false,
            openCreateChannel: false,
            openJoinChannel: false,
            openChaincodeEvent: false,

            ccInstantiateOption: {},
            ccInstallOption: {},
            ccExecuteOption: {},
            ledgerQueryOption: {},
            channelCreateOption: {},
            channelJoinOption: {},
            ccEventOption: {},

            // Initial chaincodes, all from channel chaincodes.
            mergedCCs: this.mergeCCs([], props.channelChaincodes),
            // Means installed chaincodes query error, or, it is the initial state, not sure of installed chaincodes.
            installedCCQueryError: true
        };

        this.isRunning = true;

        if (!this.state.peer) {
            this.state.peer = {};
        }

        this.handleChaincodeInstall = this.handleChaincodeInstall.bind(this);
        this.handleChaincodeInstantiate = this.handleChaincodeInstantiate.bind(this);
        this.handleChaincodeExecute = this.handleChaincodeExecute.bind(this);
        this.handleLedgerQuery = this.handleLedgerQuery.bind(this);
        this.handleChannelCreate = this.handleChannelCreate.bind(this);
        this.handleChannelJoin = this.handleChannelJoin.bind(this);
        this.handleChaincodeEvent = this.handleChaincodeEvent.bind(this);

        this.handleCloseChaincodeInstall = this.handleCloseChaincodeInstall.bind(this);
        this.handleCloseChaincodeInstantiate = this.handleCloseChaincodeInstantiate.bind(this);
        this.handleCloseChaincodeExecute = this.handleCloseChaincodeExecute.bind(this);
        this.handleCloseLedgerQuery = this.handleCloseLedgerQuery.bind(this);
        this.handleCloseChannelCreate = this.handleCloseChannelCreate.bind(this);
        this.handleCloseChannelJoin = this.handleCloseChannelJoin.bind(this);
        this.handleCloseChaincodeEvent = this.handleCloseChaincodeEvent.bind(this);

        this.discoverUpdate = this.discoverUpdate.bind(this);

        this.state.channelsAsAnchor = this.anchorChannels(this.state.peer, this.state.channelAnchorPeers);

        log.debug("PeerOverview: constructor");
    }

    anchorChannels(peer, anchorPeers) {
        const channels = [];
        for (var channel in anchorPeers) {
            for (var idx in anchorPeers[channel]) {
                if (anchorPeers[channel][idx] === peer.name || anchorPeers[channel][idx] === peer.URL) {
                    channels.push(channel);
                }
            }
        }
        return channels;
    }

    discoverUpdate() {
        const comp = this;

        // Remove the current timeout to avoid any duplicate invoking.
        // clearTimeout(this.updateTO);
        if (!comp.isRunning) {
            return;
        }

        const currIDConn = getCurrIDConn();

        const reqBody = {
            connection: currIDConn,
            target: comp.state.peer.URL,
            channels: comp.state.peer.channels || []
        };

        let myHeaders = new Headers({
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        });
        let request = new Request(CONST.getServiceURL("/peer/details"), {
            method: 'POST',
            //mode: 'cors',
            //credentials: 'include',
            headers: myHeaders,
            body: JSON.stringify(reqBody),
        });

        // TODO If the response with error, will cause a json error.
        fetch(request)
            .then(response => response.json())
            .then(result => {
                log.debug("Peer details result", comp.state.peer.URL, result);
                if (comp.isRunning) {
                    if (result) {
                        const mergedCCs = comp.mergeCCs(result.installedChaincodes, result.channelChaincodes);
                        comp.setState({
                            mergedCCs: mergedCCs,
                            installedCCQueryError: result.installedCCQueryError,
                            channelLedgers: result.channelLedgers,
                            peer: { ...comp.state.peer, channels: result.channels }
                        });
                    }
                    // TODO timeout
                    comp.updateTO = setTimeout(comp.discoverUpdate, 30000);
                }
            });
    }

    componentDidMount() {
        log.debug("PeerOverview: componentDidMount");
        if (this.state.peer) {
            // TODO stop
            this.discoverUpdate();
        }
    }

    componentDidUpdate() {
    }

    componentWillUnmount() {
        log.debug("Clear timeout task of the peer overview update");
        //clearTimeout(this.updateTO);  // To avoid memory leak.
        this.isRunning = false;
        clearTimeout(this.updateTO);
    }

    handleChannelJoin(peer) {
        const comp = this;
        return function () {
            comp.setState({ openJoinChannel: true });
            comp.setState({
                channelJoinOption: {
                    peer: peer
                }
            });
        };
    }

    handleChannelCreate() {
        const comp = this;
        return function () {
            comp.setState({ openCreateChannel: true });
            comp.setState({
                channelCreateOption: {}
            });
        };
    }


    handleChaincodeInstall(peer, name, version, type, path) {
        const comp = this;
        return function () {
            comp.setState({ openInstallChaincode: true });

            comp.setState({
                ccInstallOption: {
                    name: name,
                    version: version,
                    type: type,
                    path: path,
                    target: peer
                }
            });
        };
    }

    handleChaincodeInstantiate(existInstantiatedCC, name, version, path, policy, constructor, channelID, peer, orderer) {
        const comp = this;
        return function () {
            comp.setState({ openInstantiateChaincode: true });

            // TODO HACK MOCKING
            // comp.state.channelOrderers["mychannel"][0].name="orderer2.example.com:8050";
            // comp.state.channelOrderers["mychannel"][0].URL="orderer2.example.com:8050";

            comp.setState({
                ccInstantiateOption: {
                    // Predefined
                    existInstantiatedCC,
                    name: name,
                    version: version,
                    path: path,
                    policy: policy,
                    constructor: constructor,
                    channelID: channelID,
                    peer: peer,
                    orderer: orderer,
                    // Options
                    channelOrderers: comp.state.channelOrderers,
                }
            });
        }
    }

    handleChaincodeEvent(channelID, chaincodeID) {
        const comp = this;
        return function () {
            comp.setState({ openChaincodeEvent: true });
            comp.setState({
                ccEventOption: {
                    channelID: channelID,
                    chaincodeID: chaincodeID                    
                }
            });
        }
    }

    getChannelPeers(channelID) {
        const peers = [];
        (this.state.peers || []).forEach(peer => {
            if ((peer.channels || []).includes(channelID)) {
                peers.push(peer);
            }
        });
        return peers;
    }

    handleChaincodeExecute(actionType, channelID, name, peer) {
        const comp = this;
        return function () {
            comp.setState({ openExecuteChaincode: true });

            comp.setState({
                ccExecuteOption: {
                    actionType: actionType,
                    channelID: channelID,
                    name: name,
                    peer: peer,
                    targets: comp.getChannelPeers(channelID)
                }
            });
        };
    }

    handleLedgerQuery(channelID, target) {
        const comp = this;
        return function () {
            comp.setState({
                openLedgerDetail: true,
                ledgerQueryOption: {
                    channelID: channelID,
                    target: target
                }
            });
        };
    }

    handleCloseChaincodeInstall() {
        this.setState({ openInstallChaincode: false });
    }

    handleCloseChaincodeInstantiate() {
        this.setState({ openInstantiateChaincode: false });
    }

    handleCloseChaincodeExecute() {
        this.setState({ openExecuteChaincode: false });
    }

    handleCloseLedgerQuery() {
        this.setState({ openLedgerDetail: false });
    }

    handleCloseChannelJoin() {
        this.setState({ openJoinChannel: false });
    }

    handleCloseChannelCreate() {
        this.setState({ openCreateChannel: false });
    }

    handleCloseChaincodeEvent() {
        this.setState({ openChaincodeEvent: false });
    }

    timeLast(t) {
        // const last = ((new Date()).getTime() - t) / 1000; // Second
        // if (last < 0) {
        //     return i18n("time_last_update_invalid");
        // }
        // const hour = last / 3600;
        // const minute = (last % 3600) / 60;
        // const second = last % 60;
        const last = new Date(t);
        const hour = last.getHours();
        const minute = last.getMinutes();
        const second = last.getSeconds();
        let timeRes = `${hour}:${minute}:${second}`;
        return timeRes;
    }

    mergeCCs(installedCCs, channelChaincodes) {
        const instCCs = installedCCs || [];
        const chanCCs = channelChaincodes || [];
        var ccs = [];

        for (var channelID in chanCCs) {
            for (var i in (chanCCs[channelID] || [])) {
                const instantiatedCC = chanCCs[channelID][i];
                const idxList = this.findAllCCsIdxByName(instCCs, instantiatedCC);
                if (idxList.length <= 0) {
                    instantiatedCC.installed = false;
                    ccs.push(instantiatedCC);   // To install, 
                }
                else {
                    instantiatedCC.installed = true;
                    ccs.push(instantiatedCC);   // To query, execute

                    for (var j in idxList) {
                        const idx = idxList[j];
                        const installedCC = instCCs[idx];
                        if (instantiatedCC.version !== installedCC.version) {
                            installedCC.instantiatedCC = instantiatedCC;
                            // ccs.push(installedCC);  // To upgrade
                        }
                        else {
                            instCCs[idx] = undefined;   // Remove what found same name and version
                        }                        
                    }                    
                }
            }
        }
        // Add all installed remained, to instantiate
        instCCs.forEach(cc => {
            if (cc) {
                // const idx = this.findAllCCsIdxByName(ccs, cc);
                // if (idx >= 0 && ccs[idx].channelID) {
                //     cc.instantiatedCC = ccs[idx];
                // }
                ccs.push(cc);
            }
        });

        ccs = ccs.sort(function (a, b) {
            if (a.channelID !== b.channelID) {
                if (!a.channelID) {
                    return 1;
                }
                if (!b.channelID) {
                    return -1;
                }
                return a.channelID.localeCompare(b.channelID);
            }
            if (a.name !== b.name) {
                return a.name.localeCompare(b.name);
            }
            return a.version.localeCompare(b.version);
        });

        return ccs;
    }

    // flatChannelChaincodes(ccs) {
    //     const flatCCs = [];
    //     for (var channelID in ccs) {
    //         for (var idx in ccs[channelID]) {
    //             flatCCs.push(ccs[channelID][idx]);
    //         }
    //     }
    //     return flatCCs;
    // }

    findAllCCsIdxByName(ccList, cc) {
        const idxList = [];
        if (!ccList || !cc) {
            return idxList;
        }
        for (var idx in ccList) {
            if (ccList[idx] && ccList[idx].name === cc.name) {
                idxList.push(idx)
            }
        }
        return idxList;
    }

    getLedgerAction(channelID, target) {
        return (
            <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                onClick={this.handleLedgerQuery(channelID, target)}
            >
                {i18n("ledger_query")}
            </Button>);
    }

    getChaincodeAction(cc, peer) {
        var executeAction = null;
        var installAction = null;
        var instantiateAction = null;

        // if (cc.installed && cc.channelID) {\
        // Allow query/execute regardless of installed, user can switch target.
        if (cc.channelID) {
            executeAction = (
                <React.Fragment>
                    <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                        onClick={this.handleChaincodeExecute("query", cc.channelID, cc.name, peer)}>
                        {i18n("query")}
                    </Button>
                    <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                        onClick={this.handleChaincodeExecute("execute", cc.channelID, cc.name, peer)}>
                        {i18n("execute")}
                    </Button>
                    <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                        onClick={this.handleChaincodeEvent(cc.channelID, cc.name)}>
                        {i18n("event")}
                    </Button>
                </React.Fragment>);
        }

        // Means surely !installed
        if (!this.state.installedCCQueryError && !cc.installed) {
            installAction = (
                //name, version, path, policy, constructor, channelID, targetEndpoint, ordererEndpoint,
                //channelIDList, ordererEndpointList
                <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                    onClick={this.handleChaincodeInstall(this.state.peer, cc.name, cc.version, cc.type, cc.path)}
                    value={cc.name + ":" + cc.version}>{i18n("install")}
                </Button>);
        }

        if (cc.installed && !cc.channelID) {
            instantiateAction = (
                <Button size="small" color="primary" style={{ marginLeft: "auto", fontSize: 11 }}
                    onClick={this.handleChaincodeInstantiate(cc.instantiatedCC, cc.name, cc.version, cc.path, "", "", "",
                        this.state.peer, "")}
                    value={cc.name + ":" + cc.version}>{i18n(cc.instantiatedCC ? "upgrade" : "instantiate")}
                </Button>
            );

        }

        return (
            <React.Fragment>
                {executeAction}
                {installAction}
                {instantiateAction}
            </React.Fragment>
        );
    }

    getChaincodeTable(mergedCCs, peer) {
        const classes = this.props.classes;
        return (<Table stickyHeader className={classes.table} size="small" aria-label="chaincodes">
            <TableHead>
                <TableRow>
                    <TableCell>{i18n("chaincode")}</TableCell>
                    <TableCell align="right">{i18n("version")}</TableCell>
                    <TableCell align="right">{i18n("channel")}</TableCell>
                    <TableCell align="right">{i18n("chaincode_operation")}</TableCell>
                </TableRow>
            </TableHead>

            {/* TODO there is a key duplication issue when mouse hover. */}
            <TableBody key={"tbody_cc_" + peer.name}>
                {mergedCCs.map((cc) => {
                    return (
                        <TableRow key={"instantiate_" + cc.name + cc.version + cc.channelID + peer.name}>
                            <TableCell component="th" scope="row"><Typography noWrap className={classes.fieldDetail}>{cc.name}</Typography></TableCell>
                            <TableCell align="right"><Typography noWrap className={classes.fieldDetail}>{cc.version}</Typography></TableCell>
                            <TableCell align="right"><Typography noWrap className={classes.fieldDetail}>{cc.channelID}</Typography></TableCell>
                            <TableCell align="right">{this.getChaincodeAction(cc, peer)}</TableCell>
                        </TableRow>
                    );
                })}
            </TableBody>
        </Table>);
    }

    getChannelTable(peer) {
        const classes = this.props.classes;
        const channelLedgers = this.state.channelLedgers || {};
        const peerChannels = peer.channels.sort(function (a, b) {
            return a.localeCompare(b);
        });

        return (<Table stickyHeader className={classes.table} size="small" aria-label="channels">
            <TableHead>
                <TableRow>
                    <TableCell>{i18n("channel")}</TableCell>
                    <TableCell>{i18n("ledger_height")}</TableCell>
                    <TableCell>{i18n("ledger_currentblockhash")}</TableCell>
                    <TableCell align="right">{i18n("channel_operation")}</TableCell>
                </TableRow>
            </TableHead>

            {/* TODO there is a key duplication issue when mouse hover. */}
            <TableBody key={"tbody_ch_" + peer.name}>
                {peerChannels.map((channel) => {
                    const ldg = channelLedgers[channel] || {};
                    return (
                        <TableRow key={"channel_" + channel + peer.name}>
                            <TableCell component="th" scope="row"><Typography noWrap className={classes.fieldDetail}>{channel}</Typography></TableCell>
                            <TableCell component="th" scope="row"><Typography noWrap className={classes.fieldDetail}>{ldg.height}</Typography></TableCell>
                            <TableCell component="th" scope="row">
                                <Tooltip interactive title={ldg.currentBlockHash || ""}>
                                    <Typography noWrap className={classes.fieldDetail}>
                                        {this.state.isFocus ? ldg.currentBlockHash : cntTrim(ldg.currentBlockHash, 20)}
                                    </Typography>
                                </Tooltip>
                            </TableCell>
                            <TableCell align="right">
                                {ldg.currentBlockHash ? this.getLedgerAction(channel, peer.URL) : null}
                            </TableCell>
                        </TableRow>
                    );
                })}
            </TableBody>
        </Table>);
    }

    render() {
        const classes = this.props.classes;

        if (!this.state.peer) {
            return ("Error! No peer result.");
        }
        const peer = this.state.peer;
        let peerStatus = {
            ping: true,
            GRPC: true,
            valid: true
        };
        for (let idx in this.state.peerStatuses) {
            if (idx === peer.name) {
                peerStatus = this.state.peerStatuses[idx];
                break;
            }
        }

        var ccs = {};
        if (this.state.mergedCCs) {
            this.state.mergedCCs.forEach(cc => {
                ccs[cc.name] = "";
            });
        }
        var ccsStr = Object.keys(ccs).join(", ") || i18n("chaincode_noany");

        var chs = {};
        if (peer.channels) {
            peer.channels.forEach(ch => {
                chs[ch] = "";
            });
        }

        var channels = Object.keys(chs);

        channels = channels.sort(function (a, b) {
            return a.localeCompare(b);
        });

        var chsStr = channels.join(", ") || i18n("channel_noany");

        return (
            <React.Fragment>
                <Card> {/* className={peer.isConnected ? classes.highLightCard : classes.card} */}
                    <CardActions>
                        <Chip variant="outlined" color="primary" label={i18n("peer")} size="small" />
                        <Chip variant="outlined" label={cntTrim(peer.MSPID, 20)} size="small" />

                        {
                            this.state.channelsAsAnchor && this.state.channelsAsAnchor.length > 0 ? (
                                <Chip variant="outlined" label={i18n("anchor")} size="small" />
                            ) : null
                        }
                        
                        {!this.state.isFocus ?
                            (<Tooltip title={i18n("show_details")}>
                                <IconButton aria-label={i18n("show_details")} size="small" style={{ marginLeft: "auto" }} onClick={this.state.onFocus}>
                                    <LaunchIcon fontSize="inherit" color="primary" />
                                </IconButton>
                            </Tooltip>)
                            :
                            (<Tooltip title={i18n("close_details")}>
                                <IconButton aria-label={i18n("close_details")} size="small" style={{ marginLeft: "auto" }} onClick={this.state.onLeaveFocus}>
                                    <CloseIcon fontSize="inherit" color="primary" />
                                </IconButton>
                            </Tooltip>)}
                    </CardActions>

                    <CardContent className={classes.cardContent}>
                        <Typography className={classes.title} noWrap>{peer.name}</Typography>
                        <Typography className={classes.normal} noWrap>{peer.URL}</Typography>

                        <div className={this.state.isFocus ? classes.detailHeaderFocused : classes.detailHeaderWidget}>
                            <Typography display="inline" className={classes.title}>{i18n("channels")}</Typography>
                            <Button size="small" color="primary" style={{ marginLeft: "auto" }} onClick={this.handleChannelCreate()}>+ {i18n("create")}</Button>
                            <Button size="small" color="primary" style={{ marginLeft: "auto" }} onClick={this.handleChannelJoin(peer)}>+ {i18n("join")}</Button>
                        </div>

                        {this.state.isFocus ?
                            (
                                <div className={classes.detailTableWrapper}>
                                    {this.getChannelTable(peer)}
                                </div>
                            )
                            :
                            (
                                <Grid container >
                                    <Grid item xs={11}>
                                        <Typography noWrap className={classes.normal}>{chsStr}</Typography>
                                    </Grid>
                                    <Grid item xs={1}>
                                        <HtmlTooltip interactive title={
                                            (peer.channels && peer.channels.length > 0 ?
                                                (
                                                    <div className={classes.tooltipTableWrapper}>
                                                        {this.getChannelTable(peer)}
                                                    </div>
                                                ) :
                                                (<Typography className={classes.normal} key={"no_channel"}>
                                                    {chsStr}
                                                </Typography>))
                                        }>
                                            <MoreIcon style={{ marginLeft: "auto" }} fontSize="inherit" color="primary" />
                                        </HtmlTooltip>
                                    </Grid>
                                </Grid>)}

                        <div className={this.state.isFocus ? classes.detailHeaderFocused : classes.detailHeaderWidget}>
                            <Typography display="inline" className={classes.title}>{i18n("chaincodes")}</Typography>
                            <Button size="small" color="primary" style={{ marginLeft: "auto" }} onClick={this.handleChaincodeInstall(this.state.peer)}>+ {i18n("install")}</Button>
                        </div>

                        {this.state.isFocus ?
                            (
                                <div className={classes.detailTableWrapper}>
                                    {this.getChaincodeTable(this.state.mergedCCs, peer)}
                                </div>
                            )
                            :
                            (
                                <Grid container >
                                    <Grid item xs={11}>
                                        <Typography noWrap className={classes.normal}>{ccsStr}</Typography>
                                    </Grid>
                                    <Grid item xs={1}>
                                        <HtmlTooltip interactive title={
                                            (this.state.mergedCCs && this.state.mergedCCs.length > 0 ?
                                                (
                                                    <div className={classes.tooltipTableWrapper}>
                                                        {this.getChaincodeTable(this.state.mergedCCs, peer)}
                                                    </div>
                                                ) :
                                                (<Typography className={classes.normal} key={"no_channel"}>
                                                    {ccsStr}
                                                </Typography>))
                                        }>
                                            <MoreIcon style={{ marginLeft: "auto" }} fontSize="inherit" color="primary" />
                                        </HtmlTooltip>
                                    </Grid>
                                </Grid>)}

                    </CardContent>
                    <CardActions>
                        <Chip color="primary" size="small" label="ping" className={peerStatus.ping ? classes.peer_status_fine : classes.peer_status_error} />
                        <Chip color="primary" size="small" label="grpc" className={peerStatus.GRPC ? classes.peer_status_fine : classes.peer_status_error} />
                        <Chip color="primary" size="small" label="valid" className={peerStatus.valid ? classes.peer_status_fine : classes.peer_status_error} />
                        <Typography className={classes.timeFlag} style={{ marginLeft: "auto" }}>{this.timeLast(peer.updateTime)}</Typography>
                    </CardActions>
                </Card>

                {
                    (this.state.openInstallChaincode) ? (
                        <ChaincodeInstall key={"ccinstall_" + this.state.openInstallChaincode}
                            open={this.state.openInstallChaincode}
                            onClose={this.handleCloseChaincodeInstall}
                            callBack={this.discoverUpdate}
                            ccInstallOption={this.state.ccInstallOption}
                        />
                    ) : null
                }

                {
                    (this.state.openInstantiateChaincode) ? (
                        <ChaincodeInstantiate key={"ccinstantiate_" + this.state.openInstantiateChaincode}
                            open={this.state.openInstantiateChaincode}
                            onClose={this.handleCloseChaincodeInstantiate}
                            callBack={this.discoverUpdate}
                            ccInstantiateOption={this.state.ccInstantiateOption}
                        />
                    ) : null
                }

                {
                    (this.state.openExecuteChaincode) ? (
                        <ChaincodeExecute key={"ccexecute_" + this.state.openExecuteChaincode}
                            open={this.state.openExecuteChaincode}
                            onClose={this.handleCloseChaincodeExecute}
                            callBack={this.discoverUpdate}
                            ccExecuteOption={this.state.ccExecuteOption}
                        />
                    ) : null
                }

                {
                    (this.state.openLedgerDetail) ? (
                        <LedgerDetail key={"ledger" + this.state.openLedgerDetail}
                            open={this.state.openLedgerDetail}
                            onClose={this.handleCloseLedgerQuery}
                            ledgerQueryOption={this.state.ledgerQueryOption}
                        />
                    ) : null
                }

                {
                    (this.state.openCreateChannel) ? (
                        <ChannelCreate key={"channelcreate_" + this.state.openCreateChannel}
                            open={this.state.openCreateChannel}
                            onClose={this.handleCloseChannelCreate}
                            callBack={this.discoverUpdate}
                            channelCreateOption={this.state.channelCreateOption}
                        />
                    ) : null
                }

                {
                    (this.state.openJoinChannel) ? (
                        <ChannelJoin key={"channeljoin_" + this.state.openJoinChannel}
                            open={this.state.openJoinChannel}
                            onClose={this.handleCloseChannelJoin}
                            // callBack={this.discoverUpdate}
                            callBack={refreshNetwork}
                            channelJoinOption={this.state.channelJoinOption}
                        />
                    ) : null
                }

                {
                    (this.state.openChaincodeEvent) ? (
                        <ChaincodeEvent key={"chaincodeevent" + this.state.openChaincodeEvent}
                            open={this.state.openChaincodeEvent}
                            onClose={this.handleCloseChaincodeEvent}
                            ccEventOption={this.state.ccEventOption}
                        />
                    ) : null
                }

            </React.Fragment>
        );
    }
}

export default withStyles(styles)(PeerOverview);